Automated merge with ssh://hg.mozilla.org/labs/weave/

This commit is contained in:
Myk Melez 2008-06-11 20:00:59 -07:00
commit 669e57136f
2 changed files with 98 additions and 3 deletions

View File

@ -48,6 +48,8 @@ Cu.import("resource://weave/util.js");
* Asynchronous generator helpers
*/
let currentId = 0;
function AsyncException(initFrame, message) {
this.message = message;
this._trace = initFrame;
@ -69,11 +71,13 @@ AsyncException.prototype = {
};
function Generator(thisArg, method, onComplete, args) {
this._outstandingCbs = 0;
this._log = Log4Moz.Service.getLogger("Async.Generator");
this._log.level =
Log4Moz.Level[Utils.prefs.getCharPref("log.logger.async")];
this._thisArg = thisArg;
this._method = method;
this._id = currentId++;
this.onComplete = onComplete;
this._args = args;
this._initFrame = Components.stack.caller;
@ -83,10 +87,15 @@ function Generator(thisArg, method, onComplete, args) {
this._initFrame = this._initFrame.caller;
}
Generator.prototype = {
get name() { return this._method.name; },
get name() { return this._method.name + "-" + this._id; },
get generator() { return this._generator; },
get cb() {
let caller = Components.stack.caller;
this._outstandingCbs++;
this._log.debug(this.name +
": self.cb generated at " +
caller.filename + ":" + caller.lineNumber);
let self = this, cb = function(data) { self.cont(data); };
cb.parentGenerator = this;
return cb;
@ -126,6 +135,7 @@ Generator.prototype = {
_handleException: function AsyncGen__handleException(e) {
if (e instanceof StopIteration) {
this._log.debug(this.name + ": End of coroutine reached.");
// skip to calling done()
} else if (this.onComplete.parentGenerator instanceof Generator) {
@ -158,12 +168,20 @@ Generator.prototype = {
}
},
_detectDeadlock: function AsyncGen_detectDeadlock() {
if (this._outstandingCbs == 0)
this._log.warn("Async method '" + this.name +
"' may have yielded without an " +
"outstanding callback.");
},
run: function AsyncGen_run() {
this._continued = false;
try {
this._generator = this._method.apply(this._thisArg, this._args);
this.generator.next(); // must initialize before sending
this.generator.send(this);
this._detectDeadlock();
} catch (e) {
if (!(e instanceof StopIteration) || !this._timer)
this._handleException(e);
@ -171,9 +189,13 @@ Generator.prototype = {
},
cont: function AsyncGen_cont(data) {
this._outstandingCbs--;
this._log.debug(this.name + ": self.cb() called, resuming coroutine.");
this._continued = true;
try { this.generator.send(data); }
catch (e) {
try {
this.generator.send(data);
this._detectDeadlock();
} catch (e) {
if (!(e instanceof StopIteration) || !this._timer)
this._handleException(e);
}
@ -199,6 +221,10 @@ Generator.prototype = {
return;
let self = this;
let cb = function() { self._done(retval); };
this._log.debug(this.name + ": done() called.");
if (this._outstandingCbs > 0)
this._log.warn("Async method '" + this.name +
"' may have outstanding callbacks.");
this._timer = Utils.makeTimerForCall(cb);
},

View File

@ -0,0 +1,69 @@
const Cu = Components.utils;
Cu.import("resource://weave/util.js");
Cu.import("resource://weave/async.js");
Function.prototype.async = Async.sugar;
var callbackQueue = [];
Utils.makeTimerForCall = function fake_makeTimerForCall(cb) {
// Just add the callback to our queue and we'll call it later, so
// as to simulate a real nsITimer.
callbackQueue.push(cb);
return "fake nsITimer";
};
function secondGen() {
let self = yield;
callbackQueue.push(self.cb);
self.done();
}
function runTestGenerator() {
let self = yield;
secondGen.async({}, self.cb);
let result = yield;
self.done();
}
function run_test() {
const Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/async.js");
var errorsLogged = 0;
function _TestFormatter() {}
_TestFormatter.prototype = {
format: function BF_format(message) {
if (message.level == Log4Moz.Level.Error)
errorsLogged += 1;
return message.loggerName + "\t" + message.levelDesc + "\t" +
message.message + "\n";
}
};
_TestFormatter.prototype.__proto__ = new Log4Moz.Formatter();
var log = Log4Moz.Service.rootLogger;
var formatter = new _TestFormatter();
var appender = new Log4Moz.DumpAppender(formatter);
log.level = Log4Moz.Level.Trace;
appender.level = Log4Moz.Level.Trace;
log.addAppender(appender);
runTestGenerator.async({});
let i = 1;
while (callbackQueue.length > 0) {
let cb = callbackQueue.pop();
cb();
i += 1;
}
do_check_eq(errorsLogged, 3);
}