build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / utils / AsyncLock.ts
CommitLineData
b9b617a2
JB
1// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
2
f31d1d0c 3import Queue from 'mnemonist/queue.js';
4f9327bf 4
1227a6f1
JB
5export enum AsyncLockType {
6 configuration = 'configuration',
7 performance = 'performance',
8}
9
4f9327bf
JB
10type ResolveType = (value: void | PromiseLike<void>) => void;
11
1227a6f1 12export 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 }
e1d9a0f4 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 49 }
e1d9a0f4 50 return AsyncLock.asyncLocks.get(type)!;
dd485b56 51 }
1227a6f1 52}