Last active
September 30, 2019 07:15
-
-
Save jdmichaud/10bc5af316b78f7300cf96eae00a76ce to your computer and use it in GitHub Desktop.
A mutex++ in javascript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function main() { | |
const throttler = new Throttler(); | |
const lock = await throttler.throttle(); | |
console.log('first lock taken'); | |
setTimeout(() => { | |
console.log('releasing first lock'); | |
lock.release(); | |
}, 2000); | |
setTimeout(async () => { | |
console.log('About to take third lock'); | |
try { | |
const lock3 = await throttler.throttle(); | |
console.log('lock3 done waiting'); | |
lock3.release(); | |
const lock4 = await throttler.throttle(); | |
console.log('lock4 went through'); | |
} catch (e) { console.log('lock2 cancelled', e); } | |
}, 1000) | |
try { | |
console.log('About to take second lock'); | |
const lock2 = await throttler.throttle(); | |
console.log('lock2 done waiting'); | |
} catch (e) { console.log('lock2 cancelled', e); } | |
} | |
window.onload = main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Mutex() { | |
// A promise representing a lock given to the running thread. | |
// The thread will be in charge of releasing the lock once done. | |
this.lockPromise = undefined; | |
// An object containing a release and reject method which controls the promise | |
// provided to the blocked thread. | |
this.block = undefined; | |
// Create the lock and return it. | |
function createLock() { | |
const lock = {}; | |
this.lockPromise = new Promise(resolve => { | |
lock.release = resolve; | |
}); | |
return lock; | |
} | |
return { | |
throttle: async () => { | |
if (this.lockPromise === undefined) { | |
// No lock yet, then just create a resolved promise and return it. | |
const promise = Promise.resolve(createLock.apply(this)); | |
this.lockPromise.then(() => { | |
// The running thread just released the lock, then if a thread was | |
// waiting, release it and provide it a new lock. | |
if (this.block !== undefined) { | |
this.block.release(Promise.resolve(createLock())); | |
this.block = undefined; | |
} | |
this.lockPromise = undefined; | |
}); | |
return promise; | |
} else { | |
if (this.block !== undefined) { | |
// Reject the previous waiting thread. | |
this.block.reject(); | |
} | |
const promise = new Promise((resolve, reject) => { | |
this.block = { | |
release: resolve, | |
reject: reject, | |
}; | |
}); | |
return promise; | |
} | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment