@nomicfoundation/ethereumjs-util
Version:
A collection of utility functions for Ethereum
43 lines (37 loc) • 1.63 kB
text/typescript
// Based on https://github.com/jsoendermann/semaphore-async-await/blob/master/src/Semaphore.ts
export class Lock {
private permits: number = 1
private promiseResolverQueue: Array<(v: boolean) => void> = []
/**
* Returns a promise used to wait for a permit to become available. This method should be awaited on.
* @returns A promise that gets resolved when execution is allowed to proceed.
*/
public async acquire(): Promise<boolean> {
if (this.permits > 0) {
this.permits -= 1
return Promise.resolve(true)
}
// If there is no permit available, we return a promise that resolves once the semaphore gets
// signaled enough times that permits is equal to one.
return new Promise<boolean>((resolver) => this.promiseResolverQueue.push(resolver))
}
/**
* Increases the number of permits by one. If there are other functions waiting, one of them will
* continue to execute in a future iteration of the event loop.
*/
public release(): void {
this.permits += 1
if (this.permits > 1 && this.promiseResolverQueue.length > 0) {
// eslint-disable-next-line no-console
console.warn('Lock.permits should never be > 0 when there is someone waiting.')
} else if (this.permits === 1 && this.promiseResolverQueue.length > 0) {
// If there is someone else waiting, immediately consume the permit that was released
// at the beginning of this function and let the waiting function resume.
this.permits -= 1
const nextResolver = this.promiseResolverQueue.shift()
if (nextResolver) {
nextResolver(true)
}
}
}
}