multithreading
Version:
The missing standard library for multithreading in JavaScript (Works in the browser, Node.js, Deno, Bun).
124 lines (123 loc) • 6.78 kB
JavaScript
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _SemaphoreGuard_amount, _SemaphoreGuard_controller, _SemaphoreGuard_released, _Semaphore_instances, _a, _Semaphore_state, _Semaphore_controller, _Semaphore_release;
import { register, Serializable, toDeserialized, toSerialized, } from "../shared.js";
export const INTERNAL_SEMAPHORE_CONTROLLER = Symbol("Thread.InternalSemaphoreController");
const IDX_PERMITS = 0;
const IDX_WAITERS = 1;
const META_SIZE = 2;
export class SemaphoreGuard {
constructor(amount, controller) {
_SemaphoreGuard_amount.set(this, void 0);
_SemaphoreGuard_controller.set(this, void 0);
_SemaphoreGuard_released.set(this, false);
__classPrivateFieldSet(this, _SemaphoreGuard_amount, amount, "f");
__classPrivateFieldSet(this, _SemaphoreGuard_controller, controller, "f");
}
get [(_SemaphoreGuard_amount = new WeakMap(), _SemaphoreGuard_controller = new WeakMap(), _SemaphoreGuard_released = new WeakMap(), INTERNAL_SEMAPHORE_CONTROLLER)]() {
return __classPrivateFieldGet(this, _SemaphoreGuard_controller, "f");
}
get amount() {
return __classPrivateFieldGet(this, _SemaphoreGuard_amount, "f");
}
[Symbol.dispose]() {
if (!__classPrivateFieldGet(this, _SemaphoreGuard_released, "f")) {
__classPrivateFieldSet(this, _SemaphoreGuard_released, true, "f");
__classPrivateFieldGet(this, _SemaphoreGuard_controller, "f").release(__classPrivateFieldGet(this, _SemaphoreGuard_amount, "f"));
}
}
dispose() {
this[Symbol.dispose]();
}
}
export class Semaphore extends Serializable {
constructor(initialCount, _buffer) {
super();
_Semaphore_instances.add(this);
_Semaphore_state.set(this, void 0);
_Semaphore_controller.set(this, void 0);
if (_buffer) {
__classPrivateFieldSet(this, _Semaphore_state, new Int32Array(_buffer), "f");
}
else {
__classPrivateFieldSet(this, _Semaphore_state, new Int32Array(new SharedArrayBuffer(META_SIZE * Int32Array.BYTES_PER_ELEMENT)), "f");
__classPrivateFieldGet(this, _Semaphore_state, "f")[IDX_PERMITS] = initialCount;
__classPrivateFieldGet(this, _Semaphore_state, "f")[IDX_WAITERS] = 0;
}
__classPrivateFieldSet(this, _Semaphore_controller, {
release: (amount) => __classPrivateFieldGet(this, _Semaphore_instances, "m", _Semaphore_release).call(this, amount),
}, "f");
}
get [(_Semaphore_state = new WeakMap(), _Semaphore_controller = new WeakMap(), _Semaphore_instances = new WeakSet(), INTERNAL_SEMAPHORE_CONTROLLER)]() {
return __classPrivateFieldGet(this, _Semaphore_controller, "f");
}
tryAcquire(amount = 1) {
const current = Atomics.load(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS);
if (current >= amount) {
const result = Atomics.compareExchange(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, current, current - amount);
if (result === current) {
return new SemaphoreGuard(amount, __classPrivateFieldGet(this, _Semaphore_controller, "f"));
}
}
return null;
}
blockingAcquire(amount = 1) {
while (true) {
const current = Atomics.load(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS);
if (current >= amount) {
const result = Atomics.compareExchange(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, current, current - amount);
if (result === current) {
return new SemaphoreGuard(amount, __classPrivateFieldGet(this, _Semaphore_controller, "f"));
}
}
else {
Atomics.add(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_WAITERS, 1);
Atomics.wait(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, current);
Atomics.sub(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_WAITERS, 1);
}
}
}
async acquire(amount = 1) {
while (true) {
const current = Atomics.load(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS);
if (current >= amount) {
const result = Atomics.compareExchange(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, current, current - amount);
if (result === current) {
return new SemaphoreGuard(amount, __classPrivateFieldGet(this, _Semaphore_controller, "f"));
}
}
else {
Atomics.add(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_WAITERS, 1);
const res = Atomics.waitAsync(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, current);
if (res.async) {
await res.value;
}
Atomics.sub(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_WAITERS, 1);
}
}
}
[(_Semaphore_release = function _Semaphore_release(amount) {
Atomics.add(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, amount);
if (Atomics.load(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_WAITERS) > 0) {
Atomics.notify(__classPrivateFieldGet(this, _Semaphore_state, "f"), IDX_PERMITS, amount);
}
}, toSerialized)]() {
return [__classPrivateFieldGet(this, _Semaphore_state, "f").buffer];
}
static [toDeserialized](buffer) {
return new _a(0, buffer);
}
}
_a = Semaphore;
(() => {
register(3, _a);
})();