const { EventEmitter, on } = require('events') class Lock { constructor () { this._locked = false this._emitter = new EventEmitter() } /** * Synchronous. Returns true if the lock was acquired. Return false if the lock is already held by something else. * @returns {boolean} */ tryAcquire () { if (!this._locked) { this._locked = true return true } return false } /** * Asynchronous. Resolves when the lock was acquired. * @returns {Promise} */ async acquire () { if (!this._locked) { this._locked = true return } // Cannot use for await without a variable. But the variable is never used. So eslint complains ¯\_(ツ)_/¯ for await (const _ of on(this._emitter, 'release')) { // eslint-disable-line if (!this._locked) { this._locked = true return } } } /** * Releases the lock. */ release () { this._locked = false setImmediate(() => this._emitter.emit('release')) } } module.exports = Lock