45 lines
814 B
TypeScript
45 lines
814 B
TypeScript
export class Semaphore {
|
|
private current = 0;
|
|
private readonly waiting: Array<() => void> = [];
|
|
|
|
constructor(private readonly limit: number) {}
|
|
|
|
get active(): number {
|
|
return this.current;
|
|
}
|
|
|
|
get queued(): number {
|
|
return this.waiting.length;
|
|
}
|
|
|
|
async use<T>(task: () => Promise<T>): Promise<T> {
|
|
await this.acquire();
|
|
|
|
try {
|
|
return await task();
|
|
} finally {
|
|
this.release();
|
|
}
|
|
}
|
|
|
|
private async acquire(): Promise<void> {
|
|
if (this.current < this.limit) {
|
|
this.current += 1;
|
|
return;
|
|
}
|
|
|
|
await new Promise<void>((resolve) => {
|
|
this.waiting.push(() => {
|
|
this.current += 1;
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
private release(): void {
|
|
this.current -= 1;
|
|
const next = this.waiting.shift();
|
|
next?.();
|
|
}
|
|
}
|