Friends at Meta mentioned to me a couple years ago that they started using c++ coroutines, which ended up being a big mistake because they had to face compiler implementation bugs, which must have been nasty to track down. At Google, we are eagerly waiting for the brilliant folks that are working on properly integrating them in google3/ to tell us when the time has come to use them.
This article uses Duff's device [1] to motivate structured gotos via macros as an implementation strategy for C coroutines. Duff wanted to loop-unroll this:
do {
*to = *from++;
} while (--count > 0);
which he did in this way (shortened for brevity) : int n = (count + 3) / 4;
switch (count % 4) {
case 0: do { *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
That is to say, he realized that he could use `case` statements (almost) anywhere in a `switch` block. The connection with coroutines is simple: One can wrap the whole function body with a switch statement, use a static variable for holding the location of the latest coroutine return, and label all co-returns with a `case` statement: #define coBegin static int state = 0; switch (state) { case 0:
#define coReturn(x) do { state = __LINE_; return x; case __LINE:; } while (0)
#define coFinish }
int function(void) {
static int i; // function state can't be local anymore.
coBegin;
for (i = 0; i < 10; ++i)
coReturn(i);
coFinish;
}
Sustrik's take on C coroutines might also be an interesting read [2].