Skip to content

Instantly share code, notes, and snippets.

@zerobias
Last active December 1, 2018 16:17
Show Gist options
  • Save zerobias/6de214b9280917fe5fd9c537b7ab308c to your computer and use it in GitHub Desktop.
Save zerobias/6de214b9280917fe5fd9c537b7ab308c to your computer and use it in GitHub Desktop.
Mutex
/* @flow */
class Lock {
release: () => void
sustain = new Promise<void>(resolve => {
this.release = resolve
})
}
export type Releaser<Key> = Promise<() => void>
export class LockPack<Key> {
lockPromises: Map<Key, Promise<void>> = new Map()
RELEASER_KEY = Symbol('releaser key')
cleanup(releaser: Releaser<Key>) {
this.lockPromises.delete((releaser: any)[this.RELEASER_KEY])
}
/**
* Acquires a mutex lock over the given key. If the lock can't be acquired, it waits until it's available.
* @param key Key to get the lock for.
* @return {Promise.<() => void>} A Promise that resolves when the lock is acquired, with the function that
* must be called to release the lock.
*/
lock(key: Key): Releaser<Key> {
const lock = new Lock()
const lockPromise = this.lockPromises.get(key) || Promise.resolve()
const releaser = lockPromise.then(() => lock.release)
const sustain = lockPromise.then(() => lock.sustain)
this.lockPromises.set(key, sustain)
;(releaser: any)[this.RELEASER_KEY] = key
return releaser
}
}
export default new LockPack<any>()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment