UNPKG

@toolbuilder/semaphore

Version:

Basic semaphore and mutex with both sync and async acquire methods.

67 lines (59 loc) 1.64 kB
'use strict'; var semaphore = require('./semaphore.js'); /** * @function * @param {import('./semaphore.js').Resolver} fn - function to call only once * @returns {() => void} */ const once = fn => { let alreadyCalled = false; return () => { if (!alreadyCalled) { alreadyCalled = true; fn(); } } }; /** * Simple mutex class. * @example * const mutex = new Mutex() * const release = await mutex.acquire() * release() // to release mutex */ class Mutex { constructor () { /** @private */ this._semaphore = new semaphore.Semaphore(1); } /** * Determine if the lock is available. * @returns {boolean} - true if lock is available, false otherwise */ available () { return this._semaphore.available() } /** * Get a lock if available. * * @returns {() => void} - if the lock is available, returns a * function to release it. Otherwise returns null. The release function can * be called multiple times, it will only release once. * @example * const mutex = new Mutex() * const release = mutex.acquireSync() * if (release) release() */ acquireSync () { const release = once(() => this._semaphore.release()); return (this._semaphore.acquireSync()) ? release : null } /** * Acquire a lock. * @returns {PromiseLike<() => void>} - returns a Promise that resolves to a release function. The release * function can be called multiple times, it will only release once. */ acquire () { const release = once(() => this._semaphore.release()); return this._semaphore.acquire().then(() => release) } } exports.Mutex = Mutex;