So users of the lock would call acquire and get back a deferred (a promise in other language), but say in the most basic way, a callback is passed to it. When lock can be acquired, that callback is called (or deferred is fired).
When done with the resource, must call the release. Release then will trigger the lock to inspect the list of available waiting clients, pick one and fire their callback letting them know they can access the resource, and so on.
https://github.com/twisted/twisted/blob/trunk/src/twisted/in...
let lock;
const log = (msg) => {
lock = new Promise(async (resolve) => {
await lock;
console.log(msg);
setTimeout(resolve, 1000);
});
};
'hello world'.split('').forEach(log);I needed it in order to use a library that had some annoying global state in it.
The read/write combinations to the semaphore variable need not be atomic since we know that if this thread is running there are no other threads that can be reading and then modifying it.
MyObject.queueSemaphore = N;
MyObject.emitter = new EventEmitter();
MyObject.queue = function( ... ){
// if this run can take place go
// otherwise wait for a run-complete to try again
if(this.queueSemaphore > 0) {
this.queueSemaphore--;
} else {
// must return a promise that resolves and possibly requeues
return new promise((resolve, reject) => {
this.emitter.once("run-complete", () => {
resolve(true);
});
}).then(() => this.queue( ... ));
}
this.promiseBasedProcess()
// ... work
.finally(() => {
this.queueSemaphore++;
this.emitter.emit("run-complete");
});
}https://bl.ocks.org/johnsonjo4531/99256568deaf8c0f1685793a4a...
Basically it is used like this:
```
var lock = new AsyncLock();
(async () => {
for await(var _ of lock) {
console.log("here 1a");
await sleep(1000);
console.log("here 1b")
}
})();
(async () => {
for await(var _ of lock) {
console.log("here 2a");
await sleep(1000);
console.log("here 2b")
}
})();
/*
When Lock is working should print:
here 1a
here 1b
here 2a
here 2b
Without the lock it would print:
here 1a
here 2a
here 1b
here 2b
*/
```If you want to check out the implementation go to the blocks link. (which is basically just a gist that you can run). Here's the actual gist link: https://gist.github.com/johnsonjo4531/99256568deaf8c0f168579....
It requires Chrome 63 (at this point Chrome Canary) because it uses async iterators. I used this because I can close the lock automatically in case an error is thrown, the loop is broken. It only iterates one value and only after the lock is unlocked.