What are use cases for coroutines?

One use case is a web server that has multiple simultaneous connections, with a requirement to schedule reading and writing in parallel with all of them.

This can be implemented using coroutines. Each connection is a coroutine that reads/writes some amount of data, then yields control to the scheduler. The scheduler passes to the next coroutine (which does the same thing), cycling through all the connections.


Use case: coroutines are often used in game programming to time-slice computations.

To maintain a consistent frame rate in a game, e.g., 60 fps, you have about 16.6ms to execute code in each frame. That includes physics simulation, input processing, drawing/painting.

Lets say your method is executed in every frame. If your method takes a long time and ends up spanning multiple frames, you are going to stagger the rest of the computation in the game loop which results in the user seeing "jank" (a sudden drop in frame rate).

Coroutines make it possible to time slice the computation so that it runs a little bit in each frame.

For that to happen, coroutines allow the method to "yield" the computation back to the "caller" (in this case the game loop) so that the next time the method is called it resumes from where it left off.


Unix pipes are a use case:

grep TODO *.c | wc -l

The pipeline above is a coroutine. The grep command generates a sequence of lines and writes them to a buffer. The wc command reads these lines from the buffer. If the buffer fills up, then grep "blocks" until the buffer empties. If the buffer is empty, then wc waits for more input in the buffer.

Coroutines are more often used in more constrained patterns, like the Python generators mentioned, or as pipelines.

For more details and examples, read the Wikipedia articles, particularly coroutines and iterators.


True coroutines require language support. They need to be implemented by the compiler and supported by the underlying framework.

One language-supported implementation of coroutines is the C# 2.0 yield return keyword, which allows you to write a method that returns multiple values for looping.

The yield return does have limitations, however. The implementation uses a helper class to capture state, and it only supports the specific case of a coroutine as a generator (iterator).

In a more general case, an advantage of coroutines is that they make certain state-based computations easier to express and easier to understand. For example, implementing a state machine as a set of coroutines can be more elegant than other implementations. But doing this requires language support that doesn't yet exist in C# or Java.