Skip to content

Instantly share code, notes, and snippets.

@yashLadha
Last active August 18, 2020 13:36
Show Gist options
  • Save yashLadha/022444fac5edc7d712b0590b0423035a to your computer and use it in GitHub Desktop.
Save yashLadha/022444fac5edc7d712b0590b0423035a to your computer and use it in GitHub Desktop.
Native Mutex Implementation in NodeJS
'use strict';
const EventEmitter = require('events');
class NativeLock extends EventEmitter {
lockState = new Map();
constructor() {
super();
this.on('lock', this.handleLockAquire);
this.on('release', this.releaseLock);
}
releaseLock(key, res) {
console.log(`Releasing lock for ${key}`);
this.lockState.delete(key);
res();
}
async handleLockAquire(key, res) {
console.log(`Acquiring lock for ${key}`);
this.lockState.set(key, 'acquired');
res();
}
release(key) {
return new Promise((res) => {
this.emit('release', key, res);
});
}
static delay(ms) {
return new Promise((res) => {
setTimeout(res, ms);
});
}
acquire(key) {
return new Promise((res) => {
// Leveraging TCO (Tail call optimization)
// for recusrive calls and not overflowing the stack
// frames
const timer = async () => {
if (this.lockState.has(key)) {
console.log(`Lock already acquired for ${key}`);
await NativeLock.delay(50);
return timer();
}
this.emit('lock', key, res);
};
timer();
});
}
}
// Lock object to handle the locking in asynchronous code
const lock = new NativeLock();
const KEY = 'sameKey';
const OTHER_KEY = 'anotherKey';
const main = async() => {
await Promise.all(Array.from(Array(5)).map(async (_, idx) => {
const localKey = idx % 2 === 0 ? KEY : OTHER_KEY;
await lock.acquire(localKey);
// Having some action for 5 seconds
await NativeLock.delay(5000);
await lock.release(localKey);
}));
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment