igir
Version:
🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.
38 lines (37 loc) • 1.38 kB
JavaScript
import { Semaphore } from 'async-mutex';
/**
* Wrapper for an `async-mutex` {@link Semaphore} that can have its total increased if a weight
* exceeds the maximum.
*/
export default class ElasticSemaphore {
semaphoreValue;
semaphore;
_openLocks = 0;
constructor(value) {
this.semaphoreValue = Math.ceil(value);
this.semaphore = new Semaphore(this.semaphoreValue);
}
/**
* Run some {@link callback} with a required {@link weight}.
*/
async runExclusive(callback, weight) {
const weightNormalized = Math.max(1, Math.ceil(weight));
// NOTE(cemmer): this semaphore can take a measurable amount of time to actually call the
// callback. This is particularly noticeable when using single threads (e.g. via Async.js).
// Try to only use semaphores to traffic cop multiple concurrent threads.
const result = await this.semaphore.runExclusive(async (value) => {
this._openLocks += 1;
return await callback(value);
},
// If the weight of this call is larger than the max value then just use the max value
Math.min(weightNormalized, this.semaphoreValue));
this._openLocks -= 1;
return result;
}
/**
* Get the number of currently open/acquired locks.
*/
openLocks() {
return this._openLocks;
}
}