Commit | Line | Data |
---|---|---|
b9b617a2 JB |
1 | // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved. |
2 | ||
f31d1d0c | 3 | import Queue from 'mnemonist/queue.js'; |
4f9327bf | 4 | |
1227a6f1 JB |
5 | export enum AsyncLockType { |
6 | configuration = 'configuration', | |
7 | performance = 'performance', | |
8 | } | |
9 | ||
4f9327bf JB |
10 | type ResolveType = (value: void | PromiseLike<void>) => void; |
11 | ||
1227a6f1 | 12 | export class AsyncLock { |
dd485b56 | 13 | private static readonly asyncLocks = new Map<AsyncLockType, AsyncLock>(); |
7e0bf360 | 14 | private acquired: boolean; |
4f9327bf | 15 | private readonly resolveQueue: Queue<ResolveType>; |
1227a6f1 | 16 | |
42486f23 | 17 | private constructor() { |
1227a6f1 | 18 | this.acquired = false; |
4f9327bf | 19 | this.resolveQueue = new Queue<ResolveType>(); |
1227a6f1 JB |
20 | } |
21 | ||
dd485b56 JB |
22 | public static async acquire(type: AsyncLockType): Promise<void> { |
23 | const asyncLock = AsyncLock.getAsyncLock(type); | |
24 | if (!asyncLock.acquired) { | |
25 | asyncLock.acquired = true; | |
acf727c7 | 26 | return; |
1227a6f1 | 27 | } |
acf727c7 | 28 | return new Promise((resolve) => { |
4f9327bf | 29 | asyncLock.resolveQueue.enqueue(resolve); |
acf727c7 | 30 | }); |
1227a6f1 JB |
31 | } |
32 | ||
dd485b56 JB |
33 | public static async release(type: AsyncLockType): Promise<void> { |
34 | const asyncLock = AsyncLock.getAsyncLock(type); | |
4f9327bf | 35 | if (asyncLock.resolveQueue.size === 0 && asyncLock.acquired) { |
dd485b56 | 36 | asyncLock.acquired = false; |
1227a6f1 JB |
37 | return; |
38 | } | |
4f9327bf | 39 | const queuedResolve = asyncLock.resolveQueue.dequeue(); |
1227a6f1 JB |
40 | return new Promise((resolve) => { |
41 | queuedResolve(); | |
42 | resolve(); | |
43 | }); | |
44 | } | |
dd485b56 JB |
45 | |
46 | private static getAsyncLock(type: AsyncLockType): AsyncLock { | |
47 | if (!AsyncLock.asyncLocks.has(type)) { | |
42486f23 | 48 | AsyncLock.asyncLocks.set(type, new AsyncLock()); |
dd485b56 JB |
49 | } |
50 | return AsyncLock.asyncLocks.get(type); | |
51 | } | |
1227a6f1 | 52 | } |