File "ReadWriteLock.js"
Full Path: /srv/www/www.cadoro.it/app/lib/locks/lib/ReadWriteLock.js
File size: 2.74 KB
MIME-type: text/plain
Charset: utf-8
function ReadWriteLock() {
this.isLocked = false;
this._readLocks = 0;
this._waitingToRead = [];
this._waitingToWrite = [];
}
module.exports = ReadWriteLock;
ReadWriteLock.prototype.readLock = function (cb) {
if (this.isLocked === 'W') {
this._waitingToRead.push(cb);
} else {
this._readLocks += 1;
this.isLocked = 'R';
cb.call(this);
}
};
ReadWriteLock.prototype.writeLock = function (cb) {
if (this.isLocked) {
this._waitingToWrite.push(cb);
} else {
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() {
clearTimeout(timer);
if (cb) {
var callback = cb;
cb = null;
callback.apply(that, arguments);
}
}
this._waitingToRead.push(waiter);
timer = setTimeout(function () {
var index = that._waitingToRead.indexOf(waiter);
if (index !== -1) {
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() {
clearTimeout(timer);
if (cb) {
var callback = cb;
cb = null;
callback.apply(that, arguments);
}
}
this._waitingToWrite.push(waiter);
timer = setTimeout(function () {
var index = that._waitingToWrite.indexOf(waiter);
if (index !== -1) {
that._waitingToWrite.splice(index, 1);
waiter(new Error('WriteLock timed out'));
}
}, ttl);
};
ReadWriteLock.prototype.tryReadLock = function () {
if (this.isLocked === 'W') {
return false;
}
this.isLocked = 'R';
this._readLocks += 1;
return true;
};
ReadWriteLock.prototype.tryWriteLock = function () {
if (this.isLocked) {
return false;
}
this.isLocked = 'W';
return true;
};
ReadWriteLock.prototype.unlock = function () {
var waiter;
if (this.isLocked === 'R') {
this._readLocks -= 1;
if (this._readLocks === 0) {
// allow one write lock through
waiter = this._waitingToWrite.shift();
if (waiter) {
this.isLocked = 'W';
waiter.call(this);
} else {
this.isLocked = false;
}
}
} else if (this.isLocked === 'W') {
// allow all read locks or one write lock through
var rlen = this._waitingToRead.length;
if (rlen === 0) {
waiter = this._waitingToWrite.shift();
if (waiter) {
this.isLocked = 'W';
waiter.call(this);
} else {
this.isLocked = false;
}
} 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);
}
}
} else {
throw new Error('ReadWriteLock is not locked');
}
};