/** * represents an acquired lock that can be released */ export interface Lock extends Disposable { dispose(): void; } /** * provides mutual exclusion for async operations */ class Mutex { #promise = Promise.resolve(); /** * acquires the mutex, blocking until available * @returns a lock that must be disposed to release the mutex */ async acquire(): Promise { const { promise, resolve } = Promise.withResolvers(); const previous = this.#promise; this.#promise = promise; await previous; return { [Symbol.dispose]: resolve, dispose: resolve }; } } export default Mutex;