Skip to content

Instantly share code, notes, and snippets.

@creationix
Created November 8, 2011 22:14
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save creationix/1349451 to your computer and use it in GitHub Desktop.
Save creationix/1349451 to your computer and use it in GitHub Desktop.
Lua style coroutines in nodeJS proposal
var FS = require('fs');
var Fiber = require('./fiber'); // Not to be confused with the existing node-fibers module
// readFile is a normal non-blocking, async function, but internally it can use
// the coroutine helper fiber. These kinds of coroutines are no more dangerous
// to the caller than any other async function.
function readfile(filename, next) {
// The call to Fiber is non-blocking. It's contents are only run sync till
// the first call to wait and then it returns.
Fiber(function (resume, wait) {
var err, fd, stat, chunks;
console.log("opening...");
// This is a normal async function. It doesn't know anything about coroutines.
// The FS.open call is non-blocking, even for this coroutine
FS.open(filename, "r", "0644", resume);
// Destructuring assignment, wait returns the arguments that resume got.
// The call to wait will suspend this coroutine and only resume when the
// `resume` callback eventually gets called.
[err, fd] = wait();
if (err) { next(err); return; }
// Same thing, but doing a fstat on the fd
console.log("fstatting...");
FS.fstat(fd, resume);
[err, stat] = wait();
if (err) { next(err); return; }
// Here is an example using a blocking loop to read a file in chunks
console.log("reading...");
var chunk, length, offset = 0;
do {
FS.read(fd, offset, 72, resume);
[err, chunk, length] = wait();
if (err) { next(err); return; }
chunks.push(chunk);
offset = offset + length;
} while (length);
console.log("pausing...");
// Works for other async functions too, not just node ones.
// Sleep this coroutine for 500ms
setTimeout(resume, 500);
wait();
console.log("closing...");
FS.close(fd, resume)
[err] = wait();
if (err) { next(err); return; }
next(null, chunks, stat);
});
}
// This is the implementation of the fiber helper used in the example.
// 'coroutine' is a made up addon or builtin to future javascript
// that implements lua style coroutines.
var Coroutine = require('coroutine');
module.exports = function Fiber(fn) {
var resume = Coroutine.wrap(fn);
resume(resume, Coroutine.yield);
};
@willconant
Copy link

It looks like this is just as easy to implement with generators, which will almost certainly make it into future versions of v8, so this is probably going to be a viable strategy for future modules.

https://gist.github.com/1364503

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment