Permalink
Browse files

Better multitasking; fixed return value for callbacks with no args; f…

…ixed parser for one liners.
  • Loading branch information...
1 parent 2c942f6 commit 87391a31ab9a4823fa9130b576521e744ee15054 @lm1 committed Jan 26, 2011
Showing with 58 additions and 43 deletions.
  1. +43 −39 fiberize.js
  2. +1 −1 package.json
  3. +3 −3 test/callback_args_test.js
  4. +11 −0 test/fparse_test.js
View
@@ -28,53 +28,51 @@ module.exports.require = function(path) {
return fiberize(require(path));
};
-function build_result(result, cb_args, type) {
- var ret = {};
- if (result !== undefined) {
- ret.value = [result].concat(cb_args);
- } else if (type === 0) {
- ret.value = cb_args;
- } else {
- if (cb_args[0]) {
- ret.error = cb_args[0];
- return ret;
- } else {
- ret.value = cb_args.slice(1);
+function get_current_fiber() {
+ var f = Fiber.current;
+ if (f === undefined) throw new Error("You need to start a fiber first!");
+ if (!f.resume) {
+ f.resume = function() {
+ if (this.started) this.run();
+ else throw new Error("The fiber is not started!");
}
}
- if (ret.value.length == 1) ret.value = ret.value[0];
- return ret;
+ return f;
}
function wrapf(fn, type) {
return function() {
var args = Array.prototype.slice.call(arguments);
- var fiber = Fiber.current;
- var returned = false;
+ var fiber = get_current_fiber();
var result;
var cb_args;
var cb = function(err) {
cb_args = Array.prototype.slice.call(arguments);
- if (!returned) return true;
- var ret = build_result(result, cb_args, type);
- if (ret.error) {
- fiber.throwInto(ret.error);
- return false;
- } else {
- fiber.run(ret.value);
- return true;
+ if (Fiber.current !== fiber) {
@ybogdanov

ybogdanov Feb 12, 2011

Excuse me, can you explain the logic of this check?

@lm1

lm1 Feb 12, 2011

Owner

This is to handle the case where the callback is called directly from wrapped function (not async), thus from same fiber. It should have been done in resume actually, but in current codebase there is no resume method added and native Fiber.run is used (with no check Fiber.run would start a new fiber in this case causing a disaster).

@ybogdanov

ybogdanov Feb 12, 2011

Have you ever seen such error?

node(14593) malloc: *** error for object 0x100916ce0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
/Users/octave/bin/fiber-shim: line 25: 14593 Abort trap FIBER_SHIM=1 DYLD_INSERT_LIBRARIES="$FIBERS_ROOT/coroutine.dylib" DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_LIBRARY_PATH="$FIBERS_ROOT" "$@"

@lm1

lm1 Feb 12, 2011

Owner

Yes, unfortunately there is a problem in node-fibers (at least on some systems), please post it here: https://github.com/laverdet/node-fibers/issues

@lm1

lm1 Feb 21, 2011

Owner

The issue has been resolved by node-fibers 1.8.

+ fiber.resume();
}
};
args.push(cb);
- var value = fn.apply(this, args);
- returned = true;
- if (value !== this) result = value;
- if (cb_args) {
- var ret = build_result(result, cb_args, type);
- if (ret.error) throw (ret.error);
- else return ret.value;
+ var result = fn.apply(this, args);
+ if (result === this) {
+ result = undefined;
}
- return yield();
+ while (!cb_args) {
+ yield();
+ }
+ if (result !== undefined) {
+ result = [result].concat(cb_args);
+ } else if (type === 0) {
+ result = cb_args;
+ } else {
+ var err = cb_args.shift();
+ if (err) throw err;
+ result = cb_args;
+ }
+ if (result.length <= 1) {
+ result = result[0];
+ }
+ return result;
}
}
@@ -85,7 +83,7 @@ function fiberize(obj) {
if (typeof fn !== 'function' || /^_.*|.*_$/.test(f)) continue;
var body = fn.toString(); // stringify function body
// extract arguments (including the commented ones)
- var args = /function [\w$]*\((.*)\)\s*{/.exec(body)[1]
+ var args = /function [\w$]*\((.*?)\)\s*{/.exec(body)[1]
.replace(/\/\*|\*\//g, ', ')
.replace(/\s*/g, '')
.replace(/,,/g, ',')
@@ -106,22 +104,28 @@ function fiberize(obj) {
return obj;
}
-module.exports.start = function(f) {
+fiberize.start = function(f) {
return Fiber(function(args) {
return f.apply(this, args);
}).run(Array.prototype.slice.call(arguments, 1));
};
-module.exports.task = function(f) {
+fiberize.task = function(f) {
return function() {
Fiber(function(args) {f.apply(this, args);}).run(arguments);
};
};
-module.exports.sleep = function(ms) {
- var fiber = Fiber.current;
- setTimeout(function() { fiber.run(); }, ms);
- yield();
+fiberize.sleep = function(ms) {
+ var wake = false;
+ var fiber = get_current_fiber();
+ setTimeout(function() {
+ wake = true;
+ fiber.resume();
+ }, ms);
+ while (!wake) {
+ yield();
+ }
};
require('fs').readFile.__hasCallback = true;
View
@@ -1,6 +1,6 @@
{
"name": "fiberize",
- "description": "Node API wrapper for use with node-fibers.",
+ "description": "Node API wrapper for use with fibers.",
"version": "0.0.1",
"url": "http://github.com/lm1/node-fiberize",
"author": "Lukasz Mielicki <mielicki@gmail.com>",
@@ -120,9 +120,9 @@ fiberize.start(function() {
});
} else {
result = fw.apply(null, args);
- }
- if (f.result) {
- assert.deepEqual(result, f.result);
+ console.log('Result', result);
+ if (f.result) assert.deepEqual(result, f.result);
+ else assert.strictEqual(result, f.result);
}
}
View
@@ -0,0 +1,11 @@
+var fiberize = require('fiberize');
+var assert = require('assert');
+
+var obj = {
+ f1: function(callback) { if (true, true) { }}
+};
+
+fiberize(obj);
+assert.ok(typeof obj.f1W === 'function');
+
+process.nextTick(function() { console.log('_END_');});

0 comments on commit 87391a3

Please sign in to comment.