7f44bd257251f32cde860ce6a40d6eb82cf1a51c
[e-mobility-charging-stations-simulator.git] / src / utils / AsyncLock.ts
1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
2
3 export enum AsyncLockType {
4 configuration = 'configuration',
5 performance = 'performance',
6 }
7
8 export class AsyncLock {
9 private static readonly asyncLocks = new Map<AsyncLockType, AsyncLock>();
10 private acquired: boolean;
11 private readonly resolveQueue: ((value: void | PromiseLike<void>) => void)[];
12
13 private constructor(private readonly type: AsyncLockType) {
14 this.acquired = false;
15 this.resolveQueue = [];
16 }
17
18 public static async acquire(type: AsyncLockType): Promise<void> {
19 const asyncLock = AsyncLock.getAsyncLock(type);
20 if (!asyncLock.acquired) {
21 asyncLock.acquired = true;
22 } else {
23 return new Promise((resolve) => {
24 asyncLock.resolveQueue.push(resolve);
25 });
26 }
27 }
28
29 public static async release(type: AsyncLockType): Promise<void> {
30 const asyncLock = AsyncLock.getAsyncLock(type);
31 if (asyncLock.resolveQueue.length === 0 && asyncLock.acquired) {
32 asyncLock.acquired = false;
33 return;
34 }
35 const queuedResolve = asyncLock.resolveQueue.shift();
36 return new Promise((resolve) => {
37 queuedResolve();
38 resolve();
39 });
40 }
41
42 private static getAsyncLock(type: AsyncLockType): AsyncLock {
43 if (!AsyncLock.asyncLocks.has(type)) {
44 AsyncLock.asyncLocks.set(type, new AsyncLock(type));
45 }
46 return AsyncLock.asyncLocks.get(type);
47 }
48 }