Last active
August 22, 2025 20:22
-
-
Save tomtheisen/42bfdd1bc0011964acb4ecec54fc77c6 to your computer and use it in GitHub Desktop.
Promise Queue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function promiseAndCallbacks() { | |
| let resolve: () => void; | |
| let reject: (reason?: any) => void; | |
| const promise = new Promise<void>((res, rej) => { | |
| resolve = res; | |
| reject = rej; | |
| }); | |
| return { promise, resolve, reject }; | |
| } | |
| export type MutexLockHandle = { | |
| release: () => void; | |
| } | |
| /** | |
| * A simple mutex for async code. | |
| * Usage: | |
| * const mutex = new Mutex(); | |
| * | |
| * async function criticalSection() { | |
| * const lock = await mutex.acquireLock(); | |
| * try { | |
| * // critical section code, must be async | |
| * } | |
| * finally { lock.release(); } | |
| * } | |
| */ | |
| export class Mutex { | |
| // Infinitely chained promise queue | |
| // This is not a memory leak, as resolved promises are GC'd | |
| // Verified using browser heap snapshots with millions of locks acquired/released | |
| #queue: Promise<void> = Promise.resolve(); | |
| async acquireLock(): Promise<MutexLockHandle> { | |
| const pac = promiseAndCallbacks(); | |
| const originalQueue = this.#queue; | |
| this.#queue = this.#queue.then(() => pac.promise); | |
| await originalQueue; | |
| return { release: pac.resolve }; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment