-
Notifications
You must be signed in to change notification settings - Fork 0
/
libLocks.min.js
17 lines (17 loc) · 4.89 KB
/
libLocks.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ==UserScript==
// ==UserLibrary==
// @name libLocks
// @namespace https://openuserjs.org/users/Anakunda
// @version 1.00
// @author Wizcorp Open Source
// @license MIT
// @copyright 2021, Wizcorp Open Source (https://github.com/Wizcorp)
// @description https://github.com/Wizcorp/locks
// @exclude *
// ==/UserScript==
// ==/UserLibrary==
function CondVariable(initialValue){this._value=initialValue,this._waiting=[]}function condToFunc(cond){if('function'==typeof cond)return cond;if('number'==typeof cond||'boolean'==typeof cond||'string'==typeof cond)return function(value){return value===cond};if(cond&&'object'==typeof cond&&cond instanceof RegExp)return function(value){return cond.test(value)};throw new TypeError('Unknown condition type: '+typeof cond)}function Mutex(){this._isLocked=!1,this._waiting=[]}function ReadWriteLock(){this._isLocked=!1,this._readLocks=0,this._waitingToRead=[],this._waitingToWrite=[]}function Semaphore(initialCount){this._count=initialCount||1,this._waiting=[]}CondVariable.prototype.get=function(){return this._value},CondVariable.prototype.wait=function(cond,cb){var test=condToFunc(cond);if(test(this._value))return cb.call(this);this._waiting.push({test:test,cb:cb})},CondVariable.prototype.set=function(value){this._value=value;for(var i=0;i<this._waiting.length;i++){var waiter=this._waiting[i];waiter.test(value)&&(this._waiting.splice(i,1),i-=1,waiter.cb.call(this))}},Mutex.prototype.lock=function(cb){this._isLocked?this._waiting.push(cb):(this._isLocked=!0,cb.call(this))},Mutex.prototype.timedLock=function(ttl,cb){if(!this._isLocked)return this._isLocked=!0,cb.call(this);var timer,that=this;this._waiting.push((function(){clearTimeout(timer),cb?(cb.call(this),cb=null):that.unlock()})),timer=setTimeout((function(){cb&&(cb.call(this,new Error('Lock timed out')),cb=null)}),ttl)},Object.defineProperty(Mutex.prototype,'isLocked',{get:function(){return this._isLocked}}),Mutex.prototype.tryLock=function(){return!this._isLocked&&(this._isLocked=!0,!0)},Mutex.prototype.unlock=function(){if(!this._isLocked)throw new Error('Mutex is not locked');var waiter=this._waiting.shift();waiter?waiter.call(this):this._isLocked=!1},Mutex.prototype.resetQueue=function(){this._waiting=[]},ReadWriteLock.prototype.readLock=function(cb){'W'===this._isLocked?this._waitingToRead.push(cb):(this._readLocks+=1,this._isLocked='R',cb.call(this))},ReadWriteLock.prototype.writeLock=function(cb){this._isLocked?this._waitingToWrite.push(cb):(this._isLocked='W',cb.call(this))},ReadWriteLock.prototype.timedReadLock=function(ttl,cb){if(this.tryReadLock())return cb.call(this);var timer,that=this;function waiter(){if(clearTimeout(timer),cb){var callback=cb;cb=null,callback.apply(that,arguments)}}this._waitingToRead.push(waiter),timer=setTimeout((function(){var index=that._waitingToRead.indexOf(waiter);-1!==index&&(that._waitingToRead.splice(index,1),waiter(new Error('ReadLock timed out')))}),ttl)},ReadWriteLock.prototype.timedWriteLock=function(ttl,cb){if(this.tryWriteLock())return cb.call(this);var timer,that=this;function waiter(){if(clearTimeout(timer),cb){var callback=cb;cb=null,callback.apply(that,arguments)}}this._waitingToWrite.push(waiter),timer=setTimeout((function(){var index=that._waitingToWrite.indexOf(waiter);-1!==index&&(that._waitingToWrite.splice(index,1),waiter(new Error('WriteLock timed out')))}),ttl)},Object.defineProperty(ReadWriteLock.prototype,'isReadLocked',{get:function(){return'R'===this._isLocked}}),Object.defineProperty(ReadWriteLock.prototype,'isWriteLocked',{get:function(){return'W'===this._isLocked}}),ReadWriteLock.prototype.tryReadLock=function(){return'W'!==this._isLocked&&(this._isLocked='R',this._readLocks+=1,!0)},ReadWriteLock.prototype.tryWriteLock=function(){return!this._isLocked&&(this._isLocked='W',!0)},ReadWriteLock.prototype.unlock=function(){var waiter;if('R'===this._isLocked)this._readLocks-=1,0===this._readLocks&&((
// allow one write lock through
waiter=this._waitingToWrite.shift())?(this._isLocked='W',waiter.call(this)):this._isLocked=!1);else{if('W'!==this._isLocked)throw new Error('ReadWriteLock is not locked');
// allow all read locks or one write lock through
var rlen=this._waitingToRead.length;if(0===rlen)(waiter=this._waitingToWrite.shift())?(this._isLocked='W',waiter.call(this)):this._isLocked=!1;else{this._isLocked='R',this._readLocks=rlen;var waiters=this._waitingToRead.slice();this._waitingToRead=[];for(var i=0;i<rlen;i++)waiters[i].call(this)}}},Semaphore.prototype.wait=function(cb){this._count-=1,this._count<0?this._waiting.push(cb):cb.call(this)},Semaphore.prototype.signal=function(){if(this._count+=1,this._count<=0){var waiter=this._waiting.shift();waiter&&waiter.call(this)}};const createCondVariable=function(initialValue){return new CondVariable(initialValue)},createSemaphore=function(initialCount){return new Semaphore(initialCount)},createMutex=function(){return new Mutex},createReadWriteLock=function(){return new ReadWriteLock};