A coroutine is a generalization of the subroutine. Forget for a moment everything you've been taught about calling functions, and stacks, etc... Imagine a more powerful GOTO that could jump back and forth between functions, passing arguments, and you begin to get the idea. Coroutines are a bit of ancient forgotten computer-science lore; stamped out of the collective memory by the hegemony of C. But they are useful in a wide variety of situations that can only be clumsily solved using "standard" tools like threads and processes (Multi Threaded). Coroutines can be used to simplify just about any difficult Finite State Machine programming problem. Any time you find yourself tempted to build a complex state machine to solve what should be a simple problem, you've actually been pining for coroutines. With them, you can usually turn an "inside-out" problem into a "right-side-out" problem, and replace a few pages of hairy code with a single function.
In languages that does not support coroutines directly, threads can serve as a possible workaround. Coroutines and threads may be used for the same purpose but they are definitively not the same. Coroutines share one processor with (at the level of the coroutines primitives) explicit transfer of control where threads may be executed in parallel or participate in time-sharing (without explicit control of transfer). One problem with coroutines is that blocking I/O causes the coroutines to block.
Systems which are non-pre-emptive and may only ever have a single active flow of control (regardless of the number of processors available) are referred to as coroutine systems. Coroutine programming requires quite a different approach from threads-based (Multi Threaded) programming, as many of the synchronisation and resource-sharing problems which occur in threaded environments need never trouble the coroutines programmer.
Coroutines are a natural way of expressing many algorithms, such as Simulation-s, games, asynchronous I/O, and other forms of event- driven programming or co-operative multitasking. Python's Generator functions are almost coroutines - but not quite - in that they allow pausing execution to produce a value, but do not provide for values or exceptions to be passed in when execution resumes. They also do not allow execution to be paused within the "try" portion of try/finally blocks, and therefore make it difficult for an aborted coroutine to clean up after itself... In effect, this example emulates simple tasklets as are used in StackLess Python, as long as you use a yield expression to invoke routines that would otherwise "block".
Since coroutines are strictly better than Twisted Matrix (same benefits, but easier to code), if I can't support Twisted, I'm going to push harder for Iron Port to open source its coroutines library and its version of StackLess Python.
Edited: | Tweet this!