NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // ==UserLibrary== // @name async-mutex // @namespace https://openuserjs.org/users/Anakunda // @description https://github.com/PelionIoT/async-mutex // @copyright 2021, PelionIoT (https://github.com/PelionIoT) // @license MIT // @version 1.00 // @author PelionIoT // @exclude * // ==/UserScript== // ==/UserLibrary== 'use strict' /** * An asynchronous analog to a mutex * in multithreaded programming. This is * used to coordinate access to a series * of asynchronous callbacks or chained * promises. In asynchronous programming * the same chain of promises executed * twice can become intermixed during * execution such that the sequence of * the first effectively happens in parallel * with the second. * * @class AsyncMutex * @constructor * * @example * ``` * let lock = new AsyncMutex() * * function cs() { * lock.acquire().then(function() { * ... * }).then(function() { * ... * }).then(function(result) { * lock.release() * return result * }, function(error) { * lock.release() * throw error * }) * } * ``` */ class AsyncMutex { constructor() { this.queue = [ ]; this.acquired = false; } /** * This method returns a promise that resolves * as soon as all other callers of acquire() * have invoked release(). When the promise * resolves, you can access to critical section * or protected resource * * @method acquire * @return {Promise} */ acquire() { let self = this; return new Promise(function(resolve, reject) { if (self.acquired) self.queue.push(resolve); else { self.acquired = true; resolve(); } }); } /** * This method indicates that you are done * with the critical section and will give * control to the next caller to acquire() * * @method release */ release() { let next = this.queue.shift(); if (next) next(); else this.acquired = false; } /** * This method returns the length of the * number of threads waiting to acquire * this lock */ queueSize() { return this.queue.length } } class AsyncLockMap { constructor() { this.map = new Map() } acquire(key) { if (!this.map.has(key)) this.map.set(key, new AsyncMutex()); return this.map.get(key).acquire(); } release(key) { if (this.map.has(key)) { this.map.get(key).release(); if (this.map.get(key).queueSize() == 0) this.map.delete(key); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// SAFE PADDING ////////////////////////////// //////////////////////////////////////////////////////////////////////////