-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
semaphore.ts
59 lines (54 loc) · 1.42 KB
/
semaphore.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import { RawSemaphore } from "./_raw_semaphore.ts";
/**
* A semaphore that allows a limited number of concurrent executions of an operation.
*
* ```ts
* import { Semaphore } from "@core/asyncutil/semaphore";
*
* const sem = new Semaphore(5);
* const worker = () => {
* return sem.lock(async () => {
* // do something
* });
* };
* await Promise.all([...Array(10)].map(() => worker()));
* ```
*/
export class Semaphore {
#sem: RawSemaphore;
/**
* Creates a new semaphore with the specified limit.
*
* @param size The maximum number of times the semaphore can be acquired before blocking.
* @throws {RangeError} if the size is not a positive safe integer.
*/
constructor(size: number) {
this.#sem = new RawSemaphore(size);
}
/**
* Returns true if the semaphore is currently locked.
*/
get locked(): boolean {
return this.#sem.locked;
}
/**
* Returns the number of waiters that are waiting for lock release.
*/
get waiterCount(): number {
return this.#sem.waiterCount;
}
/**
* Acquires a lock on the semaphore, and invokes the specified function.
*
* @param fn The function to invoke.
* @returns A promise that resolves to the return value of the specified function.
*/
async lock<R>(fn: () => R | PromiseLike<R>): Promise<R> {
await this.#sem.acquire();
try {
return await fn();
} finally {
this.#sem.release();
}
}
}