From c4ec010b14e21a9071e9ecae6343fa6664816f0a Mon Sep 17 00:00:00 2001 From: Alisue Date: Tue, 24 Sep 2024 12:06:37 +0900 Subject: [PATCH 1/2] chore: update deno.lock --- deno.lock | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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" ] } } From 7a8c10bc902bba58bd82c3fc25f02301876d0c2c Mon Sep 17 00:00:00 2001 From: Alisue Date: Tue, 24 Sep 2024 12:06:48 +0900 Subject: [PATCH 2/2] feat(Semaphore): add `waiterCount` to reveal the number of lock waiters --- _raw_semaphore.ts | 7 +++++++ semaphore.ts | 7 +++++++ semaphore_test.ts | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) 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/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, + ]); + }, +);