[js][utility] add AsyncLock
This commit is contained in:
parent
18e8b4f44f
commit
27a4be731d
82
shared/utility/async-lock.mjs
Normal file
82
shared/utility/async-lock.mjs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
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<number>} 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);
|
||||||
|
}
|
||||||
|
};
|
@ -1,2 +1,3 @@
|
|||||||
export { areArrayBuffersEqual } from './buffer.mjs';
|
export { areArrayBuffersEqual } from './buffer.mjs';
|
||||||
export { Queue, QueueEmptyError } from './queue.mjs';
|
export { Queue, QueueEmptyError } from './queue.mjs';
|
||||||
|
export { AsyncLock } from './async-lock.mjs';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user