Implementing coroutines with ucontext

Coroutines are a way of doing cooperative multithreading where each context has it’s own stack. And they can be incredibly useful for games. (I’ll use the word context as the coroutine equivalent of a thread) The basic idea of a coroutine is that you can yield from a context in the middle of a function, and then you will continue exactly at that point when the coroutine gets called the next time.
Imagine that you want something to happen in a sequence, for example you want to spawn an enemy, show a text for two seconds, then kill the enemy and show another text for two seconds. A trivial implementation would be this:

void sudden_exploding_unit(const Vector3 & pos)
{
    std::unique_ptr<Entity> guy = spawn_entity(pos, "grunt.entity");
    sleep(1.0f);
    show_text(pos, "oh no he is exploding!", 2.0f);
    sleep(0.5f);
    explode(*guy);
    sleep(1.0f);
    show_text(pos, "well that was underwhelming", 2.0f);
}

Even though this code is simple, you would probably have a large amount of pain to implement this in a game engine, because a game can never block, and this code is sleeping all over the place. You’d probably end up writing some kind of state machine (maybe using a kismet-like scripting system) or if you’re a terrible person you’d use asynchronous callbacks. State machines can be a fine solution, but they introduce way too much infrastructure for such a trivial piece of code.

Enter coroutines. If your engine has coroutines, you can write exactly the above code. With very little downsides. Because you could just sleep like this:

void sleep(float seconds)
{
    while (seconds >= 0.0f)
    {
        yield(); // resume here next frame
        seconds -= global_dt;
    }
}

Read the rest of this entry »