Permalink
Browse files

prototype style

  • Loading branch information...
substack committed Jan 17, 2012
1 parent 3df421d commit 4093f744eaa14bec27919016db3c40f2dda9038e
Showing with 107 additions and 99 deletions.
  1. +107 −99 index.js
View
206 index.js
@@ -1,121 +1,129 @@
var EventEmitter = require('events').EventEmitter;
var Hash = require('hashish');
var hash = require('hashish');
module.exports = Resources;
module.exports = function () {
return new Resources;
}
Resources.prototype = new EventEmitter;
function Resources () {
if (!(this instanceof Resources)) return new Resources();
this.resources = {};
this.queue = [];
this.sessions = {};
this.stats = {
resources : 0,
waiting : 0,
using : 0
};
}
Resources.prototype.add = function (key, res) {
this.resources[key] = {
key : key,
resource : res,
lease : null,
emit : null,
};
this.stats.resources ++;
this.emit('stats', this.stats);
};
Resources.prototype.remove = function (key) {
delete this.resources[key];
this.emit('stats', this.stats);
};
Resources.prototype.acquire = function (ms, emit) {
var self = this;
var resources = self.resources = {};
var queue = self.queue = [];
self.using = 0;
var token;
do {
token = Math.floor(Math.random() * Math.pow(2,32)).toString(16);
} while (self.sessions[token]);
self.stats = function () {
return {
resources : Object.keys(resources).length,
waiting : queue.length,
using : self.using,
};
};
self.sessions[token] = { emit : emit, time : ms };
self.add = function (key, res) {
resources[key] = {
key : key,
resource : res,
lease : null,
emit : null,
};
self.emit('stats', self.stats());
};
emit('token', token);
self.remove = function (key) {
delete resources[key];
self.emit('stats', self.stats());
};
var avail = Object.keys(self.resources).filter(function (key) {
return self.resources[key].lease === null;
});
if (avail.length > 0) {
self.dispatch(token, avail.values[0]);
}
else {
self.queue.push(token);
self.queue.forEach(function (id, i) {
self.sessions[id].emit('spot', i + 1, self.queue.length);
});
self.emit('stats', self.stats);
}
var tokens = {};
var emitters = {};
return token;
};
Resources.prototype.release = function (token) {
var self = this;
delete self.tokens[token];
self.acquire = function (ms, emit) {
do {
var token = Math.floor(Math.random() * Math.pow(2,32)).toString(16);
} while (tokens[token]);
tokens[token] = true;
var ix = self.queue.indexOf(token);
if (ix >= 0) {
queue.splice(ix, 1);
emit('token', token);
var avail = Hash(resources).filter(function (res) {
return res.lease === null;
queue.forEach(function (id, j) {
self.sessions[id].emit('spot', j + 1, self.queue.length);
});
if (avail.length > 0) {
dispatch(avail.values[0], token, ms, emit);
}
else {
queue.push({ token : token, time : ms, emit : emit });
queue.forEach(function (x, i) {
x.emit('spot', i + 1, queue.length);
});
self.emit('stats', self.stats());
}
self.stats.waiting -= 1;
self.emit('stats', self.stats);
return token;
};
return;
}
self.release = function (token) {
delete tokens[token];
var i = queue.map(function (q) { return q.token }).indexOf(token);
if (i >= 0) { // in the queue
queue.splice(i, 1);
queue.forEach(function (x, j) {
x.emit('spot', j + 1, queue.length);
});
self.emit('stats', self.stats());
return;
}
var res = hash(resources).detect(function (r) {
return r.lease && r.lease.token == token
});
if (res) { // bound to a resource
res.emit('release');
res.lease = null;
res.emit = null;
var res = Hash(resources).detect(function (r) {
return r.lease && r.lease.token == token
});
self.stats.using -= 1;
if (res) { // bound to a resource
res.emit('release');
res.lease = null;
res.emit = null;
self.using -= 1;
var q = queue.shift();
if (q) {
dispatch(res, q.token, q.time, q.emit);
queue.forEach(function (x, i) {
x.emit('spot', i + 1, queue.length);
});
}
self.emit('stats', self.stats());
var q = queue.shift();
if (q) {
self.dispatch(q.token, res);
self.queue.forEach(function (id, i) {
self.sessions[id].emit('spot', i + 1, self.queue.length);
});
}
self.emit('stats', self.stats);
}
};
Resources.prototype.dispatch = function (token, res) {
var self = this;
var session = self.sessions[token];
res.lease = {
start : Date.now(),
time : session.time,
token : token,
};
res.lease.end = res.lease.start + ms;
res.emit = session.emit;
function dispatch (res, token, ms, emit) {
res.lease = {
start : Date.now(),
time : ms,
token : token,
};
res.lease.end = res.lease.start + ms;
res.emit = emit;
if (ms > 0) {
setTimeout(function () {
emit('expire');
self.release(token);
}, ms);
}
emit('available', res.resource, res.key, res.lease);
self.using += 1;
self.emit('stats', self.stats());
if (session.time > 0) {
setTimeout(function () {
emit('expire');
self.release(token);
}, session.time);
}
}
session.emit('available', res.resource, res.key, res.lease);
self.stats.using += 1;
self.emit('stats', self.stats);
};

0 comments on commit 4093f74

Please sign in to comment.