UNPKG

@hazae41/mutex

Version:

Rust-like Mutex for TypeScript

158 lines (154 loc) 3.51 kB
'use strict'; var future = require('@hazae41/future'); class LockedError extends Error { #class = LockedError; name = this.#class.name; constructor() { super("Locked"); } } /** * A releasable object */ class Lock { inner; release; constructor(inner, release) { this.inner = inner; this.release = release; } [Symbol.dispose]() { this.release(); } get() { return this.inner; } } /** * A semaphore with some reference and some capacity */ class Semaphore { inner; capacity; #queue = new Array(); #count = 0; constructor(inner, capacity) { this.inner = inner; this.capacity = capacity; } static void(capacity) { return new Semaphore(undefined, capacity); } get locked() { return this.#count >= this.capacity; } get count() { return this.#count; } get() { return this.inner; } /** * Get and lock or throw * @returns */ async getOrThrow() { if (this.#count >= this.capacity) throw new LockedError(); this.#count++; const dispose = () => { this.#queue.shift()?.resolve(); this.#count--; }; return new Lock(this.inner, dispose); } /** * Get and lock or wait * @returns */ async getOrWait() { this.#count++; if (this.#count > this.capacity) { const future$1 = new future.Future(); this.#queue.push(future$1); await future$1.promise; } const dispose = () => { this.#queue.shift()?.resolve(); this.#count--; }; return new Lock(this.inner, dispose); } /** * Run and lock or throw * @param callback */ async runOrThrow(callback) { if (this.#count >= this.capacity) throw new LockedError(); this.#count++; try { return await callback(this.inner); } finally { this.#queue.shift()?.resolve(); this.#count--; } } /** * Run and lock or wait * @param callback */ async runOrWait(callback) { this.#count++; if (this.#count > this.capacity) { const future$1 = new future.Future(); this.#queue.push(future$1); await future$1.promise; } try { return await callback(this.inner); } finally { this.#queue.shift()?.resolve(); this.#count--; } } } /** * A semaphore but with a capacity of 1 */ class Mutex { inner; #semaphore; constructor(inner) { this.inner = inner; this.#semaphore = new Semaphore(inner, 1); } static void() { return new Mutex(undefined); } get locked() { return this.#semaphore.locked; } get() { return this.inner; } async getOrThrow() { return await this.#semaphore.getOrThrow(); } async getOrWait() { return await this.#semaphore.getOrWait(); } async runOrThrow(callback) { return await this.#semaphore.runOrThrow(callback); } async runOrWait(callback) { return await this.#semaphore.runOrWait(callback); } } exports.Lock = Lock; exports.LockedError = LockedError; exports.Mutex = Mutex; exports.Semaphore = Semaphore; //# sourceMappingURL=mutex.cjs.map