This article is in process. The most cogent plain-language definition of coroutine that I have encountered is this: a coroutine is just a function with multiple entry and exit points. The first prerequisite to understanding how Conkeror's coroutine library works is to read and grok everything about ''generators'' in the MDC article, [[https://developer.mozilla.org/en/New_in_JavaScript_1.7|New in JavaScript 1.7]]. Generators are the !JavaScript primitive that makes it possible to suspend execution, and is thus the basic requirement for implementing coroutines in !JavaScript. Next, read [[MinibufferReadWalkthrough]]. We'll be referring to it as an example throughout this article. !JavaScript has the same kind of generators as Python, and in the Python world, they are called ''enhanced generators''. (Because prior to Python 2.5, Python had a more limited implementation.) With a coroutine, not only can the original called function yield, but any function it calls in turn (and any function to any depth in the call chain) can also yield. With generators, only the originally called function can yield. Emulating coroutines on top of generators is the point of Conkeror's coroutine library. The technique is called ''trampolining''. In a trampoline-coroutine system, a coroutine-thread is a stack of generators. Recall from [[MinibufferReadWalkthrough]] the pair `(yield CONTINUATION)` and `yield SUSPEND`. Before suspending, the coroutine needed to get a reference to its own continuation, to stash somehwere where a later event could use it to resume the suspended thread. The ''special loop'' is running inside the coroutine thread, orchestrating the proper stacking of the generators. In effect, the special loop needed to have on hand a reference to its own continuation, in order to send back to any generator that performed `(yield CONTINUATION)`. But generators are a far cry from `call/cc`. You can't call a generator with its own continuation as a parameter. However, what you can do is this: after starting the generator, have an extra yield, so that you can send the contination into it. Compare the generators of !JavaScript and Python with the coroutines of Lua. With generators, function arguments are bound ''during the creation of the generator'' and the first `send` (which starts the generator) cannot send any value except `undefined`. {{{ function my_generator (a, b, c) { var cc = yield; while (true) { // yield values here } } var cc = my_generator(1, 2, 3); // parameters bound at instantiation of the generator. cc.send(undefined); // start the generator. (no args allowed) cc.send(cc); // it's almost like call/cc! }}} = Examples = == Periodic Fetch == This example can be used as a basis for situations where you want to periodically fetch a document for automated processing. Fetching a document is an asynchronous activity, so in Conkeror, we use a coroutine to write it concisely. '''Warning: DO NOT ABUSE THIS CODE. USE IT ONLY WHERE YOU HAVE PERMISSION.''' {{{ var fetch_timer = null; function fetch_worker () { var res = yield send_http_request(load_spec({uri: "http://example.com/"})); dumpln(res.responseText); } function fetch_test () { fetch_timer = call_at_interval(function () { co_call(fetch_worker()); }, 300000); // interval of 5 minutes } function fetch_test_stop () { timer_cancel(fetch_timer); } }}} To start the polling, call `fetch_test`. To stop the polling, call `fetch_test_stop`. = Further Reading = * [[http://www.madore.org/~david/computers/callcc.html|A page about call/cc]] . Excellent explanatory material about cooperative multithreading, building up examples on familiar concepts like `setjmp/longjmp` and exceptions. * [[http://community.schemewiki.org/?call-with-current-continuation|Schemewiki: call-with-current-continuation]] . An introduction to Scheme's `call/cc` primitive, with good examples.