Skip to content

Instantly share code, notes, and snippets.

@addam
Created March 6, 2024 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save addam/dd0188532022e182433736431679fe1f to your computer and use it in GitHub Desktop.
Save addam/dd0188532022e182433736431679fe1f to your computer and use it in GitHub Desktop.
Semaphore for node.js
function createLock() {
const clients = new Map()
function nop() {
}
const lock = (id) => {
const waiting = clients.get(id)
if (!waiting) {
const queue = []
clients.set(id, queue)
const release = async() => {
clients.delete(id)
if (queue.length) {
for (const resolve of queue) {
await resolve(nop)
}
}
}
return release
}
return new Promise((resolve, reject) => {
waiting.push(resolve)
return nop
})
}
return lock
}
module.exports = createLock
async function test() {
const startTime = new Date()
function log(...args) {
console.log(new Date() - startTime, "ms:", ...args)
}
const lock = createLock();
const anotherLock = createLock();
(async() => {
const release = await lock("first")
setTimeout(async() => {
log("first long operation done")
await release()
}, 1000)
})();
(async() => {
const release = await anotherLock("first")
log("independent quick operation done")
await release()
})();
(async() => {
const release = await lock("first")
log("first quick operation done")
await release()
})();
(async() => {
const release = await lock("second")
log("second quick operation done")
await release()
})();
}
if (require.main === module) {
test()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment