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; } }