An implementation of an asynchronous semaphore that implements the PromiseLike interface.
new AsyncSemaphore()
Creates a new instance of the AsyncSemaphore class.
release(id: number): boolean
Releases the lock with the given id.
id (number)
: The id of the lock to release.
(boolean)
: Returns true if the lock was released successfully.
ReferenceError
: Throws an error if the given id is invalid.
lock(): Promise<number>
Acquires a lock and returns a promise that resolves with the id of the acquired lock.
(Promise<number>)
: Returns a promise that resolves with the id of the acquired lock.
secureRun<k extends []>(method: (...arg: k)=>any, ...params: k): Promise<void>
Acquires a lock, runs the given method with the provided parameters, and releases the lock when done.
method (Function)
: The method to run....params (any[])
: The parameters to pass to the method.
(Promise<void>)
: Returns a promise that resolves when the method has finished running and the lock has been released.
then(onfulfilled?: (value: number) => any, onrejected?: (reason: any) => any): Promise<any>
Attaches callbacks for when a lock is acquired or if an error occurs. This allows the AsyncSemaphore instance to be used as a PromiseLike object.
onfulfilled ((value: number) => any)
: A function that is called when a lock is acquired. The function receives the id of the acquired lock as its argument.onrejected ((reason: any) => any)
: A function that is called if an error occurs while acquiring a lock. The function receives the error as its argument.
(Promise<any>)
: Returns a promise that resolves with the result of the onfulfilled callback or is rejected with the result of the onrejected callback.
Here’s an example that demonstrates how to use the AsyncSemaphore class to synchronize multiple asynchronous operations:
import { AsyncSemaphore } from './con-utils/index.js';
async function main() {
const semaphore = new AsyncSemaphore();
// Using the lock method
const id1 = await semaphore.lock();
console.log('Acquired lock with id:', id1);
// Do some work here
semaphore.release(id1);
console.log('Released lock with id:', id1);
// Using the await keyword
const id2 = await semaphore;
console.log('Acquired lock with id:', id2);
// Do some work here
semaphore.release(id2);
console.log('Released lock with id:', id2);
}
main();
Here’s an example that demonstrates how to use both the then and saveRun methods of the AsyncSemaphore class in synchronous code:
import { AsyncSemaphore } from './con-utils/index.js';
const semaphore = new AsyncSemaphore();
// Using then method
semaphore.then((id) => {
console.log('Acquired lock with id:', id);
// Do some work here
semaphore.release(id); //You must release acquired lock with given id or semaphore, will nerver be released anymore.
console.log('Released lock with id:', id);
});
semaphore.secureRun((param1,param2)=>{
console.log('Running myMethod with params:', param1, param2);
// Do some work here
}, 'param1', 'param2');
Here’s an example that demonstrates how a deadlock can occur when using the AsyncSemaphore class:
import { AsyncSemaphore } from './con-utils/index.js';
async function main() {
const semaphore = new AsyncSemaphore();
// Acquiring two locks without releasing the first one
const id1 = await semaphore.lock();
console.log('Acquired lock with id:', id1);
const id2 = await semaphore.lock();
console.log('Acquired lock with id:', id2);
// Deadlock: the second lock will never be acquired because the first one is never released
}
main();