You have less worries
Yes, the sky is blue

C#’s async/await compared to protothreads in C++

12 November 2012, by Ben    5 comments

For different parts of my job, I get to work in both high level and very low level software development — developing a Windows 8 app in C# on the one hand, and writing embedded C++ code for an microcontroller with 4KB of RAM on the other.

In our embedded codebase we’ve been using our C++ version of Adam Dunkels’ protothreads, and recently I noticed how similar protothreads are to C#’s new await and async keywords. Both make asynchronous code look like “normal” imperative code with a linear flow, and both unroll to an actual state machine under the covers.

There’s a great answer on StackOverflow showing how the C# compiler does this (and you can read more in-depth here). The example on StackOverflow shows that this C# code:

async Task Demo() { 
  var v1 = foo();
  var v2 = await bar();
  more(v1, v2);
}

Is compiled down to something like this:

class _Demo {
  int _v1, _v2;
  int _state = 0; 
  Task<int> _await1;
  public void Step() {
    switch(this._state) {
    case 0: 
      this._v1 = foo();
      this._await1 = bar();
      // When the async operation completes, it will call this method
      this._state = 1;
      op.SetContinuation(Step);
    case 1:
      this._v2 = this._await1.Result; // Get the result of the operation
      more(this._v1, this._v2);
  }
}

C++ protothreads unroll to state machines in a similar way. For a (slightly more involved) example, see the protothread vs the state machine examples at my original blog entry.

C#’s async/await and protothreads are especially similar when using protothreads in C++, as both convert local variables to member variables so that they’re around next time the protothread is executed. In C#, of course, await is available at the language level, and as a result this is done automagically by the compiler. In C++, PT_WAIT is a macro whose implementation even Duff himself probably wouldn’t care for. And of course, C++ protothreads don’t use continuations.

But they both work very well for their intended use cases! In any case, I thought this similarity was pretty neat — to me C#’s approach with async/await validates the protothread concept, despite the latter being implemented at a much lower level and with hairy macros.

So if you’re doing low-level embedded development, do check out protothreads — either the straight C version or the C++ equivalent.

5 comments and pings (oldest first)

[...] Hacker News http://blog.brush.co.nz/2012/11/async-await-protothreads-cpp/ This entry was posted in Uncategorized by admin. Bookmark the [...]

Jeff Terrace 13 Nov 2012, 04:36 link

Aren’t they both preceded by the similar system, Tame, outlined in the 2007 paper Events Can Make Sense http://pdos.csail.mit.edu/papers/tame-usenix07.pdf

Ben 13 Nov 2012, 07:40 link

Jeff, you probably saw kerneis’ reply on Hacker News, but he said: Definitely not: protothreads (2006) predates Tame (2007). But all of them are somehow (great-)grandchildren of Duff’s device: http://www.lysator.liu.se/c/duffs-device.html

Valentin Milea 18 Apr 2013, 22:20 link

Hi, you might find CppAwait interesting. It emulates C#’s await on top of stackful coroutines. Not as lightweight as protothreads, but it can deal with local variables, exceptions and composing async tasks.

Add a comment

We reserve the right to edit or remove your comment if it’s spammy, offensive, unintelligible, or if you don’t give a valid email address. :-)

We’ll never share your email address.