import { Queue } from './queue.mjs'; import { Queue } from './queue.mjs'; /** * Represents an asynchronous lock for managing access to a shared resource. * @class */ export class AsyncLock { /** * Creates an instance of AsyncLock. * @constructor */ constructor() { /** * A queue to store pending requests for acquiring the lock. * @type {Queue} * @private */ this.pending_queue = new Queue(); /** * The current state of the lock. * @type {boolean} * @private */ this.state = false; /** * The ID associated with the current lock holder. * @type {number} * @private */ this.lock_id = 0; } /** * Checks the current state of the lock. * @returns {boolean} True if the lock is acquired; otherwise, false. */ query() { return this.state; } /** * Acquires the lock asynchronously. * @returns {Promise} A promise that resolves with the unique ID associated with the acquired lock. */ acquire() { if (!this.state) { this.state = true; this.lock_id += 1; return Promise.resolve(this.lock_id); } return new Promise((resolve, _reject) => this.pending_queue.push(resolve)); } /** * Releases the lock with the specified ID. * @param {number} lock_id The ID of the lock to release. */ release(lock_id) { if (!this.state || lock_id !== this.lock_id) { return; } if (this.pending_queue.empty()) { this.state = false; return; } let resolve = this.pending_queue.front(); this.pending_queue.popFront(); this.lock_id += 1; resolve(this.lock_id); } /** * Releases the lock forcefully even you are not the owner. * BE CAREFUL WHAT YOU WISH FOR!! */ forceRelease() { this.release(this.lock_id); } };