@hazae41/mutex
Version:
Rust-like Mutex for TypeScript
158 lines (154 loc) • 3.51 kB
JavaScript
'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