Files
2014-04-22 12:25:35 +10:00

87 lines
2.1 KiB
JavaScript

(function() {
if (typeof module === "undefined") self.queue = queue;
else module.exports = queue;
queue.version = "1.0.2";
var slice = [].slice;
function queue(parallelism) {
var queue = {},
active = 0, // number of in-flight deferrals
remaining = 0, // number of deferrals remaining
head, tail, // singly-linked list of deferrals
error = null,
results = [],
await = noop,
awaitAll;
if (!parallelism) parallelism = Infinity;
queue.defer = function() {
if (!error) {
var node = arguments;
node.i = results.push(undefined) - 1;
if (tail) tail._ = node, tail = tail._;
else head = tail = node;
++remaining;
pop();
}
return queue;
};
queue.await = function(f) {
await = f;
awaitAll = false;
if (!remaining) notify();
return queue;
};
queue.awaitAll = function(f) {
await = f;
awaitAll = true;
if (!remaining) notify();
return queue;
};
function pop() {
var popping;
while (popping = head && active < parallelism) {
var node = head,
f = node[0],
a = slice.call(node, 1),
i = node.i;
if (head === tail) head = tail = null;
else head = head._;
++active;
a.push(function(e, r) {
--active;
if (error != null) return;
if (e != null) {
// clearing remaining cancels subsequent callbacks
// clearing head stops queued tasks from being executed
// setting error ignores subsequent calls to defer
error = e;
remaining = results = head = tail = null;
notify();
} else {
results[i] = r;
if (--remaining) popping || pop();
else notify();
}
});
f.apply(null, a);
}
}
function notify() {
if (error != null) await(error);
else if (awaitAll) await(null, results);
else await.apply(null, [null].concat(results));
}
return queue;
}
function noop() {}
})();