diff --git a/_raw_semaphore.ts b/_raw_semaphore.ts index 5833638..493c71b 100644 --- a/_raw_semaphore.ts +++ b/_raw_semaphore.ts @@ -29,6 +29,13 @@ export class RawSemaphore { return this.#value === 0; } + /** + * Returns the number of waiters that are waiting for lock release. + */ + get waiterCount(): number { + return this.#resolves.length; + } + /** * Acquires the semaphore, blocking until the semaphore is available. */ diff --git a/deno.lock b/deno.lock index dfb8f03..90cbb0a 100644 --- a/deno.lock +++ b/deno.lock @@ -83,9 +83,12 @@ "packageJson": { "dependencies": [ "npm:@jsr/core__iterutil@^0.6.0-pre.0", + "npm:@jsr/core__unknownutil@^4.2.0", "npm:@jsr/cross__test", "npm:@jsr/std__assert", - "npm:@jsr/std__async@^1.0.3" + "npm:@jsr/std__async@^1.0.3", + "npm:@jsr/std__jsonc@^1.0.0-rc.3", + "npm:@jsr/std__path@^1.0.2" ] } } diff --git a/semaphore.ts b/semaphore.ts index 80fd18a..081bc0d 100644 --- a/semaphore.ts +++ b/semaphore.ts @@ -35,6 +35,13 @@ export class Semaphore { 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. * diff --git a/semaphore_test.ts b/semaphore_test.ts index 7081c74..5e1e94e 100644 --- a/semaphore_test.ts +++ b/semaphore_test.ts @@ -106,3 +106,56 @@ test( assertThrows(() => new Semaphore(0), RangeError); }, ); + +test( + "Semaphore.waiterCount returns the number of waiters (n=5)", + async () => { + const befores: number[] = []; + const afters: number[] = []; + const sem = new Semaphore(5); + const worker = (i: number) => { + return sem.lock(async () => { + befores.push(sem.waiterCount); + await new Promise((resolve) => setTimeout(resolve, 10 + i)); + afters.push(sem.waiterCount); + }); + }; + await Promise.all([...Array(10)].map((_, i) => worker(i))); + /** + * Worker 0 |5========5 + * Worker 1 |5=========4 + * Worker 2 |5==========3 + * Worker 3 |5===========2 + * Worker 4 |5============1 + * Worker 5 |----------4=============0 + * Worker 6 |-----------3==============0 + * Worker 7 |------------2===============0 + * Worker 8 |-------------1================0 + * Worker 9 |--------------0=================0 + */ + assertEquals(befores, [ + 5, + 5, + 5, + 5, + 5, + 4, + 3, + 2, + 1, + 0, + ]); + assertEquals(afters, [ + 5, + 4, + 3, + 2, + 1, + 0, + 0, + 0, + 0, + 0, + ]); + }, +);