First upload version 0.0.1
This commit is contained in:
97
node_modules/lifecycle-utils/dist/withLock.js
generated
vendored
Normal file
97
node_modules/lifecycle-utils/dist/withLock.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import { MultiKeyMap } from "./MultiKeyMap.js";
|
||||
const locks = new MultiKeyMap();
|
||||
export async function withLock(scope, acquireLockSignalOrCallback, callback) {
|
||||
let acquireLockSignal = undefined;
|
||||
if (acquireLockSignalOrCallback instanceof AbortSignal)
|
||||
acquireLockSignal = acquireLockSignalOrCallback;
|
||||
else if (acquireLockSignalOrCallback != null)
|
||||
callback = acquireLockSignalOrCallback;
|
||||
if (callback == null)
|
||||
throw new Error("callback is required");
|
||||
if (acquireLockSignal?.aborted)
|
||||
throw acquireLockSignal.reason;
|
||||
const scopeClone = scope.slice();
|
||||
let [queue, onDelete] = locks.get(scopeClone) || [];
|
||||
if (queue != null && onDelete != null)
|
||||
await createQueuePromise(queue, acquireLockSignal);
|
||||
else {
|
||||
queue = [];
|
||||
onDelete = [];
|
||||
locks.set(scopeClone, [queue, onDelete]);
|
||||
}
|
||||
try {
|
||||
return await callback();
|
||||
}
|
||||
finally {
|
||||
if (queue.length > 0)
|
||||
queue.shift()();
|
||||
else {
|
||||
locks.delete(scopeClone);
|
||||
while (onDelete.length > 0)
|
||||
onDelete.shift()();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if a lock is currently active for a given `scope` values.
|
||||
*/
|
||||
export function isLockActive(scope) {
|
||||
return locks.has(scope) ?? false;
|
||||
}
|
||||
/**
|
||||
* Acquire a lock for a given `scope` values.
|
||||
*/
|
||||
export function acquireLock(scope, acquireLockSignal) {
|
||||
return new Promise((accept, reject) => {
|
||||
const scopeClone = scope.slice();
|
||||
void withLock(scopeClone, acquireLockSignal, () => {
|
||||
let releaseLock;
|
||||
const promise = new Promise((accept) => {
|
||||
releaseLock = accept;
|
||||
});
|
||||
accept({
|
||||
scope: scopeClone,
|
||||
dispose() {
|
||||
releaseLock();
|
||||
},
|
||||
[Symbol.dispose]() {
|
||||
releaseLock();
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Wait for a lock to be released for a given `scope` values.
|
||||
*/
|
||||
export async function waitForLockRelease(scope, signal) {
|
||||
if (signal?.aborted)
|
||||
throw signal.reason;
|
||||
const [queue, onDelete] = locks.get(scope) ?? [];
|
||||
if (queue == null || onDelete == null)
|
||||
return;
|
||||
await createQueuePromise(onDelete, signal);
|
||||
}
|
||||
function createQueuePromise(queue, signal) {
|
||||
if (signal == null)
|
||||
return new Promise((accept) => void queue.push(accept));
|
||||
return new Promise((accept, reject) => {
|
||||
function onAcquireLock() {
|
||||
signal.removeEventListener("abort", onAbort);
|
||||
accept();
|
||||
}
|
||||
const queueLength = queue.length;
|
||||
function onAbort() {
|
||||
const itemIndex = queue.lastIndexOf(onAcquireLock, queueLength);
|
||||
if (itemIndex >= 0)
|
||||
queue.splice(itemIndex, 1);
|
||||
signal.removeEventListener("abort", onAbort);
|
||||
reject(signal.reason);
|
||||
}
|
||||
queue.push(onAcquireLock);
|
||||
signal.addEventListener("abort", onAbort);
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=withLock.js.map
|
||||
Reference in New Issue
Block a user