Skip to content
simonferquel edited this page Jan 8, 2015 · 10 revisions

Disclaimer

I, Simon Ferquel, am a humble developer working mostly in Microsoft environments using mostly C++ and C#. I picture myself as an experimented developer but not as some kind of guru or any warden of knowledge. This paper is the result of some thinking I have had lately, and might contain some wrong statements. Its published on Github on purpose, to accept feedback, pull requests and contributions. So feel free to interact, complete or correct me !

Additionnaly, I am actually not a native English speaker. I found the subject so interesting that I thought writing this paper in English was worth the effort. So please excuse the expected English-related issues (and please submit corrections!)

Why this sample ?

The await keyword and resumable functions form a proposal for a future version of C++. You can see the last version of the paper here : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4134.pdf. Await is traditionnaly understood as some magic stuff that make source code look sequencial (with all the language structure that we love in sequencial code, like loops, conditionnal statements,...) but behave asynchronously without blocking. It's fantastic for asynchronous IO, it's fantastic to synchronize various asynchronous processes (like reading asynchronously a block from a file, then pushing the block asynchronously to a web api and so on until the file is completely read), and it's pure awesomeness in term of readability and maintainability. Await appeared a few years ago in C# and it has dramatically changed the way C# developers code asynchronous workflows, and many developers who were previously afraid of asynchronous development have changed their mind thanks to await.

So why this strange sample about await in a potentially high performance 60 frame per second game loop ? It's because of how await works in term of extensibility, and how it rely on a generalization of the coroutine concept (await is not tied to threading and async I/O), and how this could help game developers to write simpler and leaner game logic related code with little to no performance penalty (and in more mature implementations, perhaps performance boosts).

What is a coroutine ?

To answer this question, first we need to remember what is a routine. A routine is something we can trigger, that runs until completion, and can optionaly produce a result. To put it clear, a routine is any kind of synchronous api or custom function. A coroutine, is something we can trigger that will eventually complete and optionaly produce a result. The important word is eventually. So a call to std::async can be considered as the invocation of a coroutine, as well as any call to an asynchronous I/O related API, as well as anything returning some kind of promise (Microsoft PPL tasks, Intel threading block tasks, std::future,...).

What do you mean as "The generalization of the coroutine concept" ?

Asynchronous I/O and Tasks are not the only types of coroutine. Await fits perfectly with them, but it is not limited to them. Anything that would not synchronously complete is a coroutine: a timer is a coroutine (completing eventually when its time has ellapsed), an animation is a coroutine (completing eventually when it has reached its final state). We can even think of "expected user interaction" as a coroutine (in a game, for example, showing a pause overlay could be thought as a coroutine completing eventually when the user click the "resume" button). In a game the whole game logic could also be considered as a coroutine executing alongside the game loop. The code related to this paper is a single-threaded DirectX based application illustrating exactly that: it shows how await can allow a developer to express the game logic in a simple, very clean, and sequencial looking way, even if at runtime it will behave as a state machine updated 60 times per second by the game loop.

TODO: finish the paper

Clone this wiki locally