`alternator` gives an async function access to data but gives it back on await points
For about two years, I had a problem in the back of my mind. I implemented the rules of a board game separately from its UI but the manner in which I had to write the rules was too tedious. The game rules were roughly specified as a function UserInput -> GameState -> (GameState, InputRequest). This API is good for UI, tests, replays and saves but slicing execution into the bite-sized pieces that happen between user input made the rules unreadable and inflexible.
At first, generators seemed like they were made for this. But their lifetimes are rather coarse: after passing in a mutable reference to the game's state, the generator never lets go of it, even if it is dropped. Basically the only way around is giving the mutable reference back every time execution is paused, which seems a bit silly. Besides, they may never get stabilized.
Recently I realized that async functions perform the job better. They can call other async functions – even concurrently, which is convenient for games with simultaneous turns. Then I happened to read about GhostCell, which caused me to write a library that seems pretty useful.
How it works:
- a GhostToken, which controls access to the game state is given to the game rules.
- a custom executor polls once
- the only way to suspend execution of the rules is through a function that first gives back the GhostToken
- the executor is wrapped so that the only way to poll again also gives back the GhostToken
Unlike passing around &mut, the GhostToken can control access to multiple things. This lets me easily implement passing in input. GhostTokens are zero-sized, so it should be possible to make passing it around very cheap. I used RefCell before but I'm didn't like the idea that it could panic because of a slight mistake.
Does a similar library already exist? Am I the only one with this problem? If not, I can add documentation and fix any issues with the API. Of course, hints on how to reduce runtime cost are also welcome.
Below is the most complex artificial test I have written so far. I haven't ported my game to this system yet.