From 9e38c46a3d171bb5c8ef6cb12f1e4eb7da1cc25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ramirez=20Vargas=2C=20Jos=C3=A9=20Pablo?= Date: Sat, 29 Aug 2026 14:25:33 -0600 Subject: [PATCH 1/3] feat!: Rename wait -> waitSync, waitAsync -> wait, acquire -> acquireSync, acquireAsync -> acquire --- src/sync/AutoResetEvent.ts | 4 ++-- src/sync/ManualResetEvent.ts | 12 +++++------ src/sync/Mutex.ts | 16 +++++++-------- src/sync/Semaphore.ts | 28 +++++++++++++------------- tests/ut/sync/AutoResetEvent.test.ts | 22 ++++++++++---------- tests/ut/sync/ManualResetEvent.test.ts | 20 +++++++++--------- tests/ut/sync/Mutex.test.ts | 26 ++++++++++++------------ tests/ut/sync/Semaphore.test.ts | 24 +++++++++++----------- 8 files changed, 76 insertions(+), 76 deletions(-) diff --git a/src/sync/AutoResetEvent.ts b/src/sync/AutoResetEvent.ts index f1fa9f5..11aefdf 100644 --- a/src/sync/AutoResetEvent.ts +++ b/src/sync/AutoResetEvent.ts @@ -32,7 +32,7 @@ export class AutoResetEvent extends Event { * @returns `'ok'` when the waiting is over because the token signaled while waiting on it, `'timed-out'` when the * specified timeout elapsed and the token did not signal, or `'not-equal'` if no wait took place. */ - static wait(token: Token, timeout?: number) { + static waitSync(token: Token, timeout?: number) { checkToken(token, ...autoResetEventIdentityData); // Performance optimization: Blind attempt. if (Atomics.compareExchange(token, 0, 1, 0) === 1) { @@ -57,7 +57,7 @@ export class AutoResetEvent extends Event { * @returns `'ok'` when the waiting is over because the token signaled while waiting on it, `'timed-out'` when the * specified timeout elapsed and the token did not signal, or `'not-equal'` if no wait took place. */ - static async waitAsync(token: Token, timeout?: number) { + static async wait(token: Token, timeout?: number) { checkToken(token, ...autoResetEventIdentityData); // Performance optimization: Blind attempt. if (Atomics.compareExchange(token, 0, 1, 0) === 1) { diff --git a/src/sync/ManualResetEvent.ts b/src/sync/ManualResetEvent.ts index 7d2bac4..2036f7b 100644 --- a/src/sync/ManualResetEvent.ts +++ b/src/sync/ManualResetEvent.ts @@ -7,12 +7,12 @@ export function isSignaled(identifierData: IdentifierData, token: Token) { return Atomics.load(token, 0) === 1; } -export function wait(identifierData: IdentifierData, token: Token, timeout?: number) { +export function waitSync(identifierData: IdentifierData, token: Token, timeout?: number) { checkToken(token, ...identifierData); return Atomics.wait(token, 0, 0, timeout); } -export async function waitAsync(identifierData: IdentifierData, token: Token, timeout?: number) { +export async function wait(identifierData: IdentifierData, token: Token, timeout?: number) { checkToken(token, ...identifierData); const result = Atomics.waitAsync(token, 0, 0, timeout); return result.async ? await result.value : result.value; @@ -52,8 +52,8 @@ export class ManualResetEvent extends Event { * @returns `'ok'` when the waiting is over because the token signaled while waiting on it, `'timed-out'` when the * specified timeout elapsed and the token did not signal, or `'not-equal'` if no wait took place. */ - static wait(token: Token, timeout?: number) { - return wait(manualResetEventIdentityData, token, timeout); + static waitSync(token: Token, timeout?: number) { + return waitSync(manualResetEventIdentityData, token, timeout); } /** * Asynchronously waits on the specified manually-resettable token to be signaled. @@ -64,7 +64,7 @@ export class ManualResetEvent extends Event { * @returns `'ok'` when the waiting is over because the token signaled while waiting on it, `'timed-out'` when the * specified timeout elapsed and the token did not signal, or `'not-equal'` if no wait took place. */ - static waitAsync(token: Token, timeout?: number) { - return waitAsync(manualResetEventIdentityData, token, timeout); + static wait(token: Token, timeout?: number) { + return wait(manualResetEventIdentityData, token, timeout); } }; diff --git a/src/sync/Mutex.ts b/src/sync/Mutex.ts index 8b3056f..3594b04 100644 --- a/src/sync/Mutex.ts +++ b/src/sync/Mutex.ts @@ -1,6 +1,6 @@ import type { Token } from "../types.js"; import { mutexIdentityData } from "./identifiers.js"; -import { acquire, acquireAsync, SemaphoreInternal, type Releaser } from "./Semaphore.js"; +import { acquireSync, acquire, SemaphoreInternal, type Releaser } from "./Semaphore.js"; /** * Synchronization object that can be used to grant a single thread exclusive access to a resource or critical section. @@ -19,7 +19,7 @@ export class Mutex extends SemaphoreInternal { * * @example * ```typescript - * const releaser = await Mutex.acquireAsync(myMutexToken); + * const releaser = await Mutex.acquire(myMutexToken); * try { * ... * } @@ -30,7 +30,7 @@ export class Mutex extends SemaphoreInternal { * @param token Mutex token to be acquired. * @returns A releaser object that can and should be used for releasing the mutex. */ - static acquire(token: Token): Releaser; + static acquireSync(token: Token): Releaser; /** * Acquires exclusivity from the specified mutex's token. * @@ -40,7 +40,7 @@ export class Mutex extends SemaphoreInternal { * * @example * ```typescript - * const releaser = await Mutex.acquireAsync(myMutexToken); + * const releaser = await Mutex.acquireSync(myMutexToken); * try { * ... * } @@ -53,11 +53,11 @@ export class Mutex extends SemaphoreInternal { * @returns A releaser object that can and should be used for releasing the mutex, or the value `'timed-out'` if * the mutex could not be acquired before the specified timeout time elapsed. */ - static acquire(token: Token, timeout: number): Releaser | "timed-out"; + static acquireSync(token: Token, timeout: number): Releaser | "timed-out"; + static acquireSync(token: Token, timeout?: number) { + return acquireSync(mutexIdentityData, token, timeout); + } static acquire(token: Token, timeout?: number) { return acquire(mutexIdentityData, token, timeout); } - static acquireAsync(token: Token, timeout?: number) { - return acquireAsync(mutexIdentityData, token, timeout); - } }; diff --git a/src/sync/Semaphore.ts b/src/sync/Semaphore.ts index 3066d34..ca6d1e1 100644 --- a/src/sync/Semaphore.ts +++ b/src/sync/Semaphore.ts @@ -46,7 +46,7 @@ function buildReleaser(token: Token) { }) as Releaser; } -export function acquire(identifierData: IdentifierData, token: Token, timeout?: number) { +export function acquireSync(identifierData: IdentifierData, token: Token, timeout?: number) { checkToken(token, ...identifierData); while (true) { const available = Atomics.load(token, 0); @@ -64,7 +64,7 @@ export function acquire(identifierData: IdentifierData, token: Token, timeout?: } } -export async function acquireAsync(identifierData: IdentifierData, token: Token, timeout?: number) { +export async function acquire(identifierData: IdentifierData, token: Token, timeout?: number) { checkToken(token, ...identifierData); while (true) { const available = Atomics.load(token, 0); @@ -101,7 +101,7 @@ export class Semaphore extends SemaphoreInternal { * * @example * ```typescript - * const releaser = Semaphore.acquire(mySemaphoreToken); + * const releaser = Semaphore.acquireSync(mySemaphoreToken); * try { * ... * } @@ -112,7 +112,7 @@ export class Semaphore extends SemaphoreInternal { * @param token Semaphore token to be acquired. * @returns A releaser object that can and should be used for releasing the semaphore. */ - static acquire(token: Token): Releaser; + static acquireSync(token: Token): Releaser; /** * Acquires a slot from the specified semaphore's token. * @@ -122,7 +122,7 @@ export class Semaphore extends SemaphoreInternal { * * @example * ```typescript - * const releaser = Semaphore.acquire(mySemaphoreToken); + * const releaser = Semaphore.acquireSync(mySemaphoreToken); * try { * ... * } @@ -135,9 +135,9 @@ export class Semaphore extends SemaphoreInternal { * @returns A releaser object that can and should be used for releasing the semaphore, or the value `'timed-out'` * if the sempahore could not be acquired before the specified timeout time elapsed. */ - static acquire(token: Token, timeout: number): 'timed-out' | Releaser; - static acquire(token: Token, timeout?: number) { - return acquire(semaphoreIdentityData, token, timeout); + static acquireSync(token: Token, timeout: number): 'timed-out' | Releaser; + static acquireSync(token: Token, timeout?: number) { + return acquireSync(semaphoreIdentityData, token, timeout); } /** @@ -149,7 +149,7 @@ export class Semaphore extends SemaphoreInternal { * * @example * ```typescript - * const releaser = await Semaphore.acquireAsync(mySemaphoreToken); + * const releaser = await Semaphore.acquire(mySemaphoreToken); * try { * ... * } @@ -160,7 +160,7 @@ export class Semaphore extends SemaphoreInternal { * @param token Semaphore token to be acquired. * @returns A releaser object that can and should be used for releasing the semaphore. */ - static acquireAsync(token: Token): Promise; + static acquire(token: Token): Promise; /** * Asynchronously acquires a slot from the specified semaphore's token. * @@ -170,7 +170,7 @@ export class Semaphore extends SemaphoreInternal { * * @example * ```typescript - * const releaser = await Semaphore.acquireAsync(mySemaphoreToken); + * const releaser = await Semaphore.acquire(mySemaphoreToken); * try { * ... * } @@ -183,8 +183,8 @@ export class Semaphore extends SemaphoreInternal { * @returns A releaser object that can and should be used for releasing the semaphore, or the value `'timed-out'` * if the sempahore could not be acquired before the specified timeout time elapsed. */ - static acquireAsync(token: Token, timeout: number): Promise<"timed-out" | Releaser>; - static acquireAsync(token: Token, timeout?: number) { - return acquireAsync(semaphoreIdentityData, token, timeout); + static acquire(token: Token, timeout: number): Promise<"timed-out" | Releaser>; + static acquire(token: Token, timeout?: number) { + return acquire(semaphoreIdentityData, token, timeout); } } diff --git a/tests/ut/sync/AutoResetEvent.test.ts b/tests/ut/sync/AutoResetEvent.test.ts index bdca6d5..10b918b 100644 --- a/tests/ut/sync/AutoResetEvent.test.ts +++ b/tests/ut/sync/AutoResetEvent.test.ts @@ -60,22 +60,22 @@ describe('AutoResetEvent', () => { }); }); - describe('static wait', () => { + describe('static waitSync', () => { it('Should throw when the given token is not the token of an AutoResetEvent object.', () => { const foreignEvent = new ManualResetEvent(); - expect(() => AutoResetEvent.wait(foreignEvent.token)).toThrow(); + expect(() => AutoResetEvent.waitSync(foreignEvent.token)).toThrow(); }); it('Should handle timeout.', () => { - const result = AutoResetEvent.wait(eventObj.token, 10); + const result = AutoResetEvent.waitSync(eventObj.token, 10); expect(result).toBe('timed-out'); }); it('Should handle immediate success when already signaled.', () => { eventObj.signal(); - const result = AutoResetEvent.wait(eventObj.token); + const result = AutoResetEvent.waitSync(eventObj.token); expect(result).toBe('not-equal'); // Verify the event auto-reset (signal was consumed) @@ -102,11 +102,11 @@ describe('AutoResetEvent', () => { }); }); - describe('static waitAsync', () => { - it('Should throw when the given token is not the token of an AutoResetEvent object.', () => { + describe('static wait', () => { + it('Should throw when the given token is not the token of an AutoResetEvent object.', async () => { const foreignEvent = new ManualResetEvent(); - expect(() => AutoResetEvent.wait(foreignEvent.token)).toThrow(); + await expect(AutoResetEvent.wait(foreignEvent.token)).rejects.toThrow(); }); it('Should handle async wait result.', async () => { // Signal the event after a short delay to test async wait @@ -114,17 +114,17 @@ describe('AutoResetEvent', () => { eventObj.signal(); }, 0); - const result = await AutoResetEvent.waitAsync(eventObj.token, 1000); + const result = await AutoResetEvent.wait(eventObj.token, 1000); expect(result).toBe('ok'); expect(Atomics.load(eventObj.token, 0)).toBe(0); }); it('Should handle sync wait result.', async () => { - // Pre-signal the event so waitAsync returns immediately + // Pre-signal the event so wait returns immediately eventObj.signal(); - const result = await AutoResetEvent.waitAsync(eventObj.token); + const result = await AutoResetEvent.wait(eventObj.token); expect(result).toBe('not-equal'); // Verify the event auto-reset (signal was consumed) @@ -132,7 +132,7 @@ describe('AutoResetEvent', () => { }); it('Should handle timeout in async wait.', async () => { - const result = await AutoResetEvent.waitAsync(eventObj.token, 10); + const result = await AutoResetEvent.wait(eventObj.token, 10); expect(result).toBe('timed-out'); }); diff --git a/tests/ut/sync/ManualResetEvent.test.ts b/tests/ut/sync/ManualResetEvent.test.ts index 0aea2ab..2a69819 100644 --- a/tests/ut/sync/ManualResetEvent.test.ts +++ b/tests/ut/sync/ManualResetEvent.test.ts @@ -60,18 +60,18 @@ describe('ManualResetEvent', () => { tokenTypeTest(AutoResetEvent, ManualResetEvent.isSignaled, ManualResetEvent); }); - describe('static wait', () => { - tokenTypeTest(AutoResetEvent, ManualResetEvent.wait, ManualResetEvent); + describe('static waitSync', () => { + tokenTypeTest(AutoResetEvent, ManualResetEvent.waitSync, ManualResetEvent); it('Should handle timeout.', () => { - const result = ManualResetEvent.wait(eventObj.token, 10); + const result = ManualResetEvent.waitSync(eventObj.token, 10); expect(result).toBe('timed-out'); }); it('Should handle immediate success when already signaled.', () => { eventObj.signal(); - const result = ManualResetEvent.wait(eventObj.token); + const result = ManualResetEvent.waitSync(eventObj.token); expect(result).toBe('not-equal'); }); @@ -94,30 +94,30 @@ describe('ManualResetEvent', () => { }); }); - describe('static waitAsync', () => { - tokenTypeTest(AutoResetEvent, ManualResetEvent.waitAsync, ManualResetEvent); + describe('static wait', () => { + tokenTypeTest(AutoResetEvent, ManualResetEvent.wait, ManualResetEvent); it('Should handle async wait result.', async () => { // Signal the event after a short delay to test async wait setTimeout(() => { eventObj.signal(); }, 0); - const result = await ManualResetEvent.waitAsync(eventObj.token, 10); + const result = await ManualResetEvent.wait(eventObj.token, 10); expect(result).toBe('ok'); }); it('Should handle sync wait result.', async () => { - // Pre-signal the event so waitAsync returns immediately + // Pre-signal the event so wait returns immediately eventObj.signal(); - const result = await ManualResetEvent.waitAsync(eventObj.token); + const result = await ManualResetEvent.wait(eventObj.token); expect(result).toBe('not-equal'); }); it('Should handle timeout in async wait.', async () => { - const result = await ManualResetEvent.waitAsync(eventObj.token, 10); + const result = await ManualResetEvent.wait(eventObj.token, 10); expect(result).toBe('timed-out'); }); diff --git a/tests/ut/sync/Mutex.test.ts b/tests/ut/sync/Mutex.test.ts index b2ba9a3..7981f57 100644 --- a/tests/ut/sync/Mutex.test.ts +++ b/tests/ut/sync/Mutex.test.ts @@ -45,19 +45,19 @@ describe('Mutex', () => { }); }); - describe('static acquire', () => { + describe('static acquireSync', () => { beforeEach(() => { mutex = new Mutex(); }); it('Should acquire immediately when mutex is available.', () => { - const releaser = Mutex.acquire(mutex.token); + const releaser = Mutex.acquireSync(mutex.token); expect(typeof releaser).toBe('function'); }); it('Should wait when mutex is not available.', async () => { - const releaser = Mutex.acquire(mutex.token); + const releaser = Mutex.acquireSync(mutex.token); const waitAcquire = (await testMutexAcquireInWorker(mutex.token)).wait; let mainThreadReleased = false; setTimeout(() => { @@ -71,25 +71,25 @@ describe('Mutex', () => { }); }); - describe('static acquireAsync', () => { + describe('static acquire', () => { beforeEach(() => { mutex = new Mutex(); }); it('Should acquire immediately when mutex is available.', async () => { - const releaser = await Mutex.acquireAsync(mutex.token); + const releaser = await Mutex.acquire(mutex.token); expect(typeof releaser).toBe('function'); }); it('Should wait asynchronously when mutex is not available.', async () => { - const releaser = Mutex.acquire(mutex.token); + const releaser = Mutex.acquireSync(mutex.token); let mainThreadReleased = false; setTimeout(() => { mainThreadReleased = true; releaser(); }, 0); - await Mutex.acquireAsync(mutex.token); + await Mutex.acquire(mutex.token); expect(mainThreadReleased).toBe(true); }); @@ -101,7 +101,7 @@ describe('Mutex', () => { }); it('Should release the mutex when called.', () => { - const releaser = Mutex.acquire(mutex.token); + const releaser = Mutex.acquireSync(mutex.token); expect(typeof releaser).toBe('function'); @@ -111,7 +111,7 @@ describe('Mutex', () => { }); it('Should throw error when called twice.', () => { - const releaser = Mutex.acquire(mutex.token); + const releaser = Mutex.acquireSync(mutex.token); releaser(); // First release @@ -125,22 +125,22 @@ describe('Mutex', () => { }); it('Should ensure the mutex cannot be acquired again asynchronously.', async () => { - const releaser1 = Mutex.acquire(mutex.token); + const releaser1 = Mutex.acquireSync(mutex.token); expect(typeof releaser1).toBe('function'); - let releaser2 = await Mutex.acquireAsync(mutex.token, 0); + let releaser2 = await Mutex.acquire(mutex.token, 0); expect(releaser2).toBe('timed-out'); let mainThreadReleased = false; setTimeout(() => { mainThreadReleased = true; releaser1(); }, 0); - releaser2 = await Mutex.acquireAsync(mutex.token); + releaser2 = await Mutex.acquire(mutex.token); expect(mainThreadReleased).toBe(true); expect(typeof releaser2).toBe('function'); }); it("Should ensure the mutex cannot be acquired from a different thread while it's held.", async () => { - const releaser1 = Mutex.acquire(mutex.token); + const releaser1 = Mutex.acquireSync(mutex.token); expect(typeof releaser1).toBe('function'); const waitAcquire = (await testMutexAcquireInWorker(mutex.token, 0)).wait; const result = await waitAcquire; diff --git a/tests/ut/sync/Semaphore.test.ts b/tests/ut/sync/Semaphore.test.ts index b7b7bc6..6c8e1d5 100644 --- a/tests/ut/sync/Semaphore.test.ts +++ b/tests/ut/sync/Semaphore.test.ts @@ -23,7 +23,7 @@ describe('Semaphore', () => { it('Should create disabled semaphore when requested.', () => { semaphore = new Semaphore(3, true); - expect(Semaphore.acquire(semaphore.token, 0)).toBe('timed-out'); + expect(Semaphore.acquireSync(semaphore.token, 0)).toBe('timed-out'); }); }); @@ -50,14 +50,14 @@ describe('Semaphore', () => { }); }); - describe('static acquire', () => { + describe('static acquireSync', () => { const initialCapacity = 2; beforeEach(() => { semaphore = new Semaphore(initialCapacity); }); it('Should acquire immediately when capacity is available.', () => { - const result = Semaphore.acquire(semaphore.token); + const result = Semaphore.acquireSync(semaphore.token); expect(result).not.toBe('timed-out'); expect(typeof result).toBe('function'); @@ -65,9 +65,9 @@ describe('Semaphore', () => { it('Should return "timed-out" when timeout occurs.', () => { for (let i = 0; i < initialCapacity; i++) { - Semaphore.acquire(semaphore.token); + Semaphore.acquireSync(semaphore.token); } - const result = Semaphore.acquire(semaphore.token, 0); + const result = Semaphore.acquireSync(semaphore.token, 0); expect(result).toBe('timed-out'); }); @@ -75,7 +75,7 @@ describe('Semaphore', () => { it('Should wait and acquire when capacity becomes available.', async () => { let releaser: Function; for (let i = 0; i < initialCapacity; i++) { - releaser = Semaphore.acquire(semaphore.token); + releaser = Semaphore.acquireSync(semaphore.token); } const waitAcquire = (await testSemaphoreAcquireInWorker(semaphore.token)).wait; releaser!(); @@ -85,23 +85,23 @@ describe('Semaphore', () => { }); }); - describe('static acquireAsync', () => { + describe('static acquire', () => { const initialCapacity = 2; beforeEach(() => { semaphore = new Semaphore(initialCapacity); }); it('Should acquire immediately when capacity is available.', async () => { - const result = await Semaphore.acquireAsync(semaphore.token); + const result = await Semaphore.acquire(semaphore.token); expect(typeof result).toBe('function'); }); it('Should return "timed-out" when timeout occurs.', async () => { for (let i = 0; i < initialCapacity; i++) { - Semaphore.acquire(semaphore.token); + Semaphore.acquireSync(semaphore.token); } - const result = await Semaphore.acquireAsync(semaphore.token, 0); + const result = await Semaphore.acquire(semaphore.token, 0); expect(result).toBe('timed-out'); }); @@ -113,7 +113,7 @@ describe('Semaphore', () => { }); it('Should release the semaphore when called.', () => { - const releaser = Semaphore.acquire(semaphore.token); + const releaser = Semaphore.acquireSync(semaphore.token); expect(typeof releaser).toBe('function'); if (typeof releaser === 'function') { @@ -123,7 +123,7 @@ describe('Semaphore', () => { }); it('Should throw error when called twice.', () => { - const releaser = Semaphore.acquire(semaphore.token); + const releaser = Semaphore.acquireSync(semaphore.token); if (typeof releaser === 'function') { releaser(); // First release From 307df804c9be87ef21e27b26d146bc02f5e3d642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ramirez=20Vargas=2C=20Jos=C3=A9=20Pablo?= Date: Sat, 29 Aug 2026 14:29:06 -0600 Subject: [PATCH 2/3] chore: Node to v26 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dfd0af5..d8084a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: test: uses: WJSoftware/cicd/.github/workflows/npm-test.yml@v0.4 with: - node-version: 24 + node-version: 26 build-script: build test-script: test build: true From b67a8ccc82f7a85756e84ffaf1900f021b662e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ramirez=20Vargas=2C=20Jos=C3=A9=20Pablo?= Date: Sat, 29 Aug 2026 14:30:38 -0600 Subject: [PATCH 3/3] chore: Upgrade workflows --- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 14829e6..28cc347 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,7 +20,7 @@ permissions: jobs: publish: - uses: WJSoftware/cicd/.github/workflows/npm-publish.yml@v0.4 + uses: WJSoftware/cicd/.github/workflows/npm-publish.yml@main with: node-version: 24 build-script: build diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d8084a5..28e287d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ on: jobs: test: - uses: WJSoftware/cicd/.github/workflows/npm-test.yml@v0.4 + uses: WJSoftware/cicd/.github/workflows/npm-test.yml@main with: node-version: 26 build-script: build