Skip to content

Instantly share code, notes, and snippets.

@cshaa
Last active June 20, 2025 09:53
Show Gist options
  • Save cshaa/bb38e03ade1cb859a0452dff138d8fd4 to your computer and use it in GitHub Desktop.
Save cshaa/bb38e03ade1cb859a0452dff138d8fd4 to your computer and use it in GitHub Desktop.
class Mutex<T> {
#locked = false
#waiters: (() => void)[] = []
#value: T
constructor(value: T) {
this.#value = value
}
lock(): Promise<MutexLock<T>> {
return new Promise((res) => {
const acquire = () => {
this.#locked = true
const getValue = () => this.#value
const setValue = (v: T) => {
this.#value = v
}
const dispose = () => {
this.#locked = false
this.#waiters.shift()?.()
}
res(new MutexLock(dispose, getValue, setValue))
}
if (this.#locked) {
this.#waiters.push(acquire)
} else {
acquire()
}
})
}
}
class MutexLock<T> {
[Symbol.dispose]!: () => void
constructor(
dispose: (() => void) | undefined,
private getValue: () => T,
private setValue: (v: T) => void
) {
this[Symbol.dispose] = () => {
dispose?.()
dispose = undefined
}
}
get value() {
return this.getValue()
}
set value(v) {
this.setValue(v)
}
}
const Mutex_ = Mutex as { new (): Mutex<void>; new <T>(value: T): Mutex<T> }
type Mutex_<T> = Mutex<T>
export { Mutex_ as Mutex }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment