locker: fix destroy method.

This commit is contained in:
Christopher Jeffrey 2016-10-09 23:50:44 -07:00
parent 24cf42e6bf
commit 0802dbbb0f
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 59 additions and 25 deletions

View File

@ -28,6 +28,7 @@ function Locker(add) {
this.jobs = []; this.jobs = [];
this.busy = false; this.busy = false;
this.destroyed = false;
this.pending = []; this.pending = [];
this.pendingMap = {}; this.pendingMap = {};
@ -81,6 +82,9 @@ Locker.prototype.lock = function lock(arg1, arg2) {
force = arg1; force = arg1;
} }
if (this.destroyed)
return Promise.reject(new Error('Locker is destroyed.'));
if (force) { if (force) {
assert(this.busy); assert(this.busy);
return Promise.resolve(utils.nop); return Promise.resolve(utils.nop);
@ -91,8 +95,9 @@ Locker.prototype.lock = function lock(arg1, arg2) {
this.pending.push(object); this.pending.push(object);
this.pendingMap[object.hash('hex')] = true; this.pendingMap[object.hash('hex')] = true;
} }
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
self.jobs.push([resolve, object]); self.jobs.push(new Job(resolve, reject, object));
}); });
} }
@ -107,7 +112,7 @@ Locker.prototype.lock = function lock(arg1, arg2) {
*/ */
Locker.prototype.unlock = function unlock() { Locker.prototype.unlock = function unlock() {
var item, resolve, object; var job;
this.busy = false; this.busy = false;
@ -117,18 +122,21 @@ Locker.prototype.unlock = function unlock() {
if (this.jobs.length === 0) if (this.jobs.length === 0)
return; return;
item = this.jobs.shift(); job = this.jobs.shift();
resolve = item[0];
object = item[1];
if (object) { if (this.destroyed) {
assert(object === this.pending.shift()); job.reject(new Error('Locker is destroyed.'));
delete this.pendingMap[object.hash('hex')]; return;
}
if (job.object) {
assert(job.object === this.pending.shift());
delete this.pendingMap[job.object.hash('hex')];
} }
this.busy = true; this.busy = true;
resolve(this.unlocker); job.resolve(this.unlocker);
}; };
/** /**
@ -136,10 +144,7 @@ Locker.prototype.unlock = function unlock() {
*/ */
Locker.prototype.destroy = function destroy() { Locker.prototype.destroy = function destroy() {
this.jobs.length = 0; this.destroyed = true;
this.busy = false;
this.pending.length = 0;
this.pendingMap = {};
}; };
/** /**
@ -152,10 +157,10 @@ Locker.prototype.onDrain = function onDrain() {
assert(this.add, 'Cannot wait for drain without add method.'); assert(this.add, 'Cannot wait for drain without add method.');
return new Promise(function(resolve, reject) { if (this.pending.length === 0)
if (self.pending.length === 0) return Promise.resolve(null);
return resolve();
return new Promise(function(resolve, reject) {
self.once('drain', resolve); self.once('drain', resolve);
}); });
}; };
@ -173,6 +178,7 @@ function MappedLock() {
this.jobs = {}; this.jobs = {};
this.busy = {}; this.busy = {};
this.destroyed = false;
} }
/** /**
@ -203,8 +209,14 @@ MappedLock.create = function create() {
MappedLock.prototype.lock = function lock(key, force) { MappedLock.prototype.lock = function lock(key, force) {
var self = this; var self = this;
if (force || key == null) { if (this.destroyed)
assert(key == null || this.busy[key]); return Promise.reject(new Error('Locker is destroyed.'));
if (key == null)
return Promise.resolve(utils.nop);
if (force) {
assert(this.busy[key]);
return Promise.resolve(utils.nop); return Promise.resolve(utils.nop);
} }
@ -212,7 +224,7 @@ MappedLock.prototype.lock = function lock(key, force) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
if (!self.jobs[key]) if (!self.jobs[key])
self.jobs[key] = []; self.jobs[key] = [];
self.jobs[key].push(resolve); self.jobs[key].push(new Job(resolve, reject));
}); });
} }
@ -232,22 +244,27 @@ MappedLock.prototype.unlock = function unlock(key) {
var self = this; var self = this;
return function unlocker() { return function unlocker() {
var jobs = self.jobs[key]; var jobs = self.jobs[key];
var resolve; var job;
delete self.busy[key]; delete self.busy[key];
if (!jobs) if (!jobs)
return; return;
resolve = jobs.shift(); job = jobs.shift();
assert(resolve); assert(job);
if (jobs.length === 0) if (jobs.length === 0)
delete self.jobs[key]; delete self.jobs[key];
if (self.destroyed) {
job.reject(new Error('Locker is destroyed.'));
return;
}
self.busy[key] = true; self.busy[key] = true;
resolve(unlocker); job.resolve(unlocker);
}; };
}; };
@ -256,10 +273,24 @@ MappedLock.prototype.unlock = function unlock(key) {
*/ */
MappedLock.prototype.destroy = function destroy() { MappedLock.prototype.destroy = function destroy() {
this.jobs = {}; this.destroyed = true;
this.busy = {};
}; };
/**
* Locker Job
* @exports Job
* @constructor
* @param {Function} resolve
* @param {Function} reject
* @param {Object?} object
*/
function Job(resolve, reject, object) {
this.resolve = resolve;
this.reject = reject;
this.object = object || null;
}
/* /*
* Expose * Expose
*/ */

View File

@ -239,6 +239,9 @@ Wallet.prototype.destroy = co(function* destroy() {
try { try {
this.db.unregister(this); this.db.unregister(this);
this.master.destroy(); this.master.destroy();
this.readLock.destroy();
this.writeLock.destroy();
this.fundLock.destroy();
} finally { } finally {
unlock2(); unlock2();
unlock1(); unlock1();