Skip to content

Instantly share code, notes, and snippets.

@zocker-160
Last active May 10, 2025 14:10
Show Gist options
  • Save zocker-160/81b11298ae3ce6358c3356e452d7d332 to your computer and use it in GitHub Desktop.
Save zocker-160/81b11298ae3ce6358c3356e452d7d332 to your computer and use it in GitHub Desktop.
simple Semaphore implementation in JavaScript
class Semaphore {
constructor(max) {
this.counter = 0;
this.waiting = [];
this.max = max;
}
acquire() {
if (this.counter < this.max) {
this.counter++;
return new Promise((resolve) => resolve());
} else {
return new Promise((resolve, err) => {
this.waiting.push({
resolve: () => {
this.counter++;
resolve();
},
err: err
});
});
}
}
isAvailable() {
return this.counter < this.max;
}
release() {
this.counter--;
if (this.waiting.length > 0 && this.counter < this.max) {
let promise = this.waiting.shift();
promise.resolve();
}
}
purge() {
let unresolved = this.waiting.length;
for (let i = 0; i < unresolved; i++) {
this.waiting[i].err('Task has been purged.');
}
this.counter = 0;
this.waiting = [];
return unresolved;
}
}
let sema = new Semaphore(1);
async function test(id) {
console.log('queueing task', id);
try {
await sema.acquire();
console.log('running task', id);
setTimeout(() => {
console.log('release task', id);
sema.release();
}, 2000);
} catch (e) {
console.error(id, e);
}
}
test(1);
test(2);
test(3);
test(4);
test(5);
setTimeout(() => {
test(10);
test(11);
test(12);
}, 1500);
setTimeout(() => {
test(20);
test(21);
test(22);
}, 2700);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment