You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
2.8 KiB
120 lines
2.8 KiB
"use strict"; |
|
var firstLineError; |
|
try {throw new Error(); } catch (e) {firstLineError = e;} |
|
var schedule = require("./schedule"); |
|
var Queue = require("./queue"); |
|
|
|
function Async() { |
|
this._customScheduler = false; |
|
this._isTickUsed = false; |
|
this._lateQueue = new Queue(16); |
|
this._normalQueue = new Queue(16); |
|
this._haveDrainedQueues = false; |
|
var self = this; |
|
this.drainQueues = function () { |
|
self._drainQueues(); |
|
}; |
|
this._schedule = schedule; |
|
} |
|
|
|
Async.prototype.setScheduler = function(fn) { |
|
var prev = this._schedule; |
|
this._schedule = fn; |
|
this._customScheduler = true; |
|
return prev; |
|
}; |
|
|
|
Async.prototype.hasCustomScheduler = function() { |
|
return this._customScheduler; |
|
}; |
|
|
|
Async.prototype.haveItemsQueued = function () { |
|
return this._isTickUsed || this._haveDrainedQueues; |
|
}; |
|
|
|
|
|
Async.prototype.fatalError = function(e, isNode) { |
|
if (isNode) { |
|
process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) + |
|
"\n"); |
|
process.exit(2); |
|
} else { |
|
this.throwLater(e); |
|
} |
|
}; |
|
|
|
Async.prototype.throwLater = function(fn, arg) { |
|
if (arguments.length === 1) { |
|
arg = fn; |
|
fn = function () { throw arg; }; |
|
} |
|
if (typeof setTimeout !== "undefined") { |
|
setTimeout(function() { |
|
fn(arg); |
|
}, 0); |
|
} else try { |
|
this._schedule(function() { |
|
fn(arg); |
|
}); |
|
} catch (e) { |
|
throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); |
|
} |
|
}; |
|
|
|
function AsyncInvokeLater(fn, receiver, arg) { |
|
this._lateQueue.push(fn, receiver, arg); |
|
this._queueTick(); |
|
} |
|
|
|
function AsyncInvoke(fn, receiver, arg) { |
|
this._normalQueue.push(fn, receiver, arg); |
|
this._queueTick(); |
|
} |
|
|
|
function AsyncSettlePromises(promise) { |
|
this._normalQueue._pushOne(promise); |
|
this._queueTick(); |
|
} |
|
|
|
Async.prototype.invokeLater = AsyncInvokeLater; |
|
Async.prototype.invoke = AsyncInvoke; |
|
Async.prototype.settlePromises = AsyncSettlePromises; |
|
|
|
|
|
function _drainQueue(queue) { |
|
while (queue.length() > 0) { |
|
_drainQueueStep(queue); |
|
} |
|
} |
|
|
|
function _drainQueueStep(queue) { |
|
var fn = queue.shift(); |
|
if (typeof fn !== "function") { |
|
fn._settlePromises(); |
|
} else { |
|
var receiver = queue.shift(); |
|
var arg = queue.shift(); |
|
fn.call(receiver, arg); |
|
} |
|
} |
|
|
|
Async.prototype._drainQueues = function () { |
|
_drainQueue(this._normalQueue); |
|
this._reset(); |
|
this._haveDrainedQueues = true; |
|
_drainQueue(this._lateQueue); |
|
}; |
|
|
|
Async.prototype._queueTick = function () { |
|
if (!this._isTickUsed) { |
|
this._isTickUsed = true; |
|
this._schedule(this.drainQueues); |
|
} |
|
}; |
|
|
|
Async.prototype._reset = function () { |
|
this._isTickUsed = false; |
|
}; |
|
|
|
module.exports = Async; |
|
module.exports.firstLineError = firstLineError;
|
|
|