state-trooper
Version:
Application State Manager
83 lines (71 loc) • 1.88 kB
JavaScript
;
// TODO: Use process.nextTick if it's available since it's more
// efficient
// http://howtonode.org/understanding-process-next-tick
// Maybe we don't even need to queue ourselves in that case?
// XXX: But http://blog.nodejs.org/2013/03/11/node-v0-10-0-stable/
// Looks like it will blow up the stack (or is that just about
// pre-empting IO (but that's already bad enough IMO)?)
// Looks like
// http://nodejs.org/api/process.html#process_process_nexttick_callback
// is the equivalent of our TASK_BATCH_SIZE
var buffers = require("./buffers");
var TASK_BATCH_SIZE = 1024;
var tasks = buffers.ring(32);
var running = false;
var queued = false;
var queue_dispatcher;
function process_messages() {
running = true;
queued = false;
var count = 0;
while (true) {
var task = tasks.pop();
if (task === buffers.EMPTY) {
break;
}
// TODO: Don't we need a try/finally here?
task();
if (count >= TASK_BATCH_SIZE) {
break;
}
count ++;
}
running = false;
if (tasks.length > 0) {
queue_dispatcher();
}
}
if (typeof MessageChannel !== "undefined") {
var message_channel = new MessageChannel();
message_channel.port1.onmessage = function(_) {
process_messages();
};
queue_dispatcher = function() {
if (!(queued && running)) {
queued = true;
message_channel.port2.postMessage(0);
}
};
} else if (typeof setImmediate !== "undefined") {
queue_dispatcher = function() {
if (!(queued && running)) {
queued = true;
setImmediate(process_messages);
}
};
} else {
queue_dispatcher = function() {
if (!(queued && running)) {
queued = true;
setTimeout(process_messages, 0);
}
};
}
exports.run = function (f) {
tasks.unbounded_unshift(f);
queue_dispatcher();
};
exports.queue_delay = function(f, delay) {
setTimeout(f, delay);
};