Simple coroutines for games in C++
ilikebigbits.com
ilikebigbits.com
If you've never read it, the Super Mario Bros 1 disassembly[1] is extremely enlightening. It feels a lot like Erlang, with individual parallel "process" actors being responsible for updating the physics of each sprite on screen—but instead of a "process" being an abstraction handled by a scheduler, it's just an entry-point function that calls a finite-state-machine-state function, then either calls a hardwired next "process" function, or a trampoline function that calls whatever is left to run in that game state. Effectively, it's a "direct-threaded next-jmp-prefetched" implementation of scheduling.
The coroutines are regular threads. The library provides an interface for syncing which makes them behave as if they were "real" coroutines. This avoids common problems you run into when making coroutines in C++ which by itself does not support coroutines natively - but it supports threads very well.
Pros: Very easy to implement and use. Will likely work very well anywhere without much thought.
Cons: Resource hungry. Not really designed for thousands of simultaneous coroutines.
It's really nice for scripting things as you can tests a bunch of conditions, yield() and then re-test without needing to build an explicit state machine. Much easier for designers to grok.
Usually done in Lua, which is a fantastic language for gamedev(low overhead, fast, coroutine support and integrates very nicely with C/C++).
It still requites a syscall and the entities being scheduled are proper kernel level threads.
So not really fibers. Pretty cool though.
Edit: autocorrect
By the way, I found barriers to be very simple to work with for some rough multithreading. Just line all the threads up, then let them go.
For this example library if your making some sort of traditional adventure game and you wanted the player to be able to save the game you'd have to restrict saving to checkpoints, use a loop with a switch (practically moving back to the state machine approach), or just split the conversation up into multiple coroutines as it progresses.
And of course, there's the whole "what to do when you need to patch the game" problem on top of all that.
Perhaps it helps
In the end, I prefer to just use mostly "stateless" Lua scripts, with all the saveable data managed in C++.
I would use an embeddable scripting language (like Duktape) for entities. The state would be available at any time. It can also be parallelized.
[1]: http://lua-users.org/wiki/PlutoLibrary see also Tamed Pluto
[2]: http://www.slideshare.net/hughreynolds/lua-and-fable-jonatha...
Basically, the game ran "scripts" (containing custom bytecode), each given its own "slot" with space for locals. Each script is run in turn, and each script must voluntarily relinquish control when appropriate.
Of course, this is a bit more advanced than simple coroutines. If you're going to the effort of creating your own embedded scripting language, you may as well an existing language like Lua.
Example code: https://github.com/scummvm/scummvm/blob/master/engines/scumm...
Edit: s/watch/switch/
Say function A calls into generator B, which has entry points X,Y,Z. Maybe you could generate code for functions A<X>, A<Y> and A<Z>, specialised on the entry point into B. When B yields, it actually "calls" the appropriate A, but does something funny with the stack pointer. Maybe?
The generated code would explode if you had too many coroutines going at once, and you need a lot of things to be known at compile time, and maybe the specific things you'd need to do to the stack would slow you down. I don't think you'd have to mess with the return address, though, so maybe it wouldn't be so bad.
In this case you wouldn't expect any call at all: the switch statement is online in the caller and standard constant propagation can remove the switch itself.
https://paoloseverini.wordpress.com/2015/03/06/stackless-cor...
1: http://www.crystalclearsoftware.com/soc/coroutine/coroutine/...
If you want to unwind, just unwind. setjmp and setcontext neither help nor hurt you here.
BTW, I'm the author of the above page. Coroutine libraries have been my personal hobby since forever.
http://felix-lang.org/$/usr/local/lib/felix/felix-2016.01.04...
I am not involved in its development.