type ReleaseFunc = ( ) => void ; export class Mutex { private readonly _queue : Array < ( relaseFunc : ReleaseFunc ) => void > = [ ] ; private _locked = false ; public async acquire ( ) { const isLocked = this . isLocked ( ) ; const releaseFunc = new Promise < ReleaseFunc > ( resolve => this . _queue . push ( resolve ) ) ; if ( ! isLocked ) { this . _tick ( ) ; } return releaseFunc ; } public isLocked ( ) { return this . _locked ; } public async runExclusive < T > ( worker ) { const release = await this . acquire ( ) ; try { return await worker ( ) ; } finally { release ( ) ; } } private _tick ( ) { const releaseFunc = this . _queue . shift ( ) ; if ( ! releaseFunc ) { return ; } const nextReleaseFunc = ( ) => { this . _locked = false ; this . _tick ( ) ; } ; this . _locked = true ; releaseFunc ( nextReleaseFunc ) ; } }