C++ coroutine tutorial

I’ve been experimenting with coroutines recently and I found that information on C++ coroutines are very difficult to find. I’m planning to write a series of C++ coroutine blogs on how to use C++ coroutines, how they work, and how to write your own library that uses C++ coroutines. My last post Basic Concepts are probably a bit too high-level and is not really meant for people who are new to C++ coroutines. So I’m going to start over with a simple C++ coroutine tutorial instead.

Enough talking. Show me the code

OK. I’m not going to bore you with the technical details (any more), and let’s jump straight into some sample code!

As you can see, this code simply calculates fibonacci, and it’s not a very good one either (again, coroutine != performance). But it’s a good one to show some basic concepts:

A C++ coroutine (such as async_fib) returns a coroutine type.

In this case, we are returningstd::future<T>. This is a standard C++ library type. Unfortunately the default implementation in most compilers don’t support using futureas a coroutine type. VC++ has its own extension that adds coroutine support to std::future. For the purpose of showing what coroutine is, we are going to assume `std::future` has that support. To run this code, you'll need VC++.

So what is a coroutine type anyway? It is a type that is aware of coroutines and implements a bunch of contracts required by C++ compilers. Most these contracts are (synchronous) callback that compiler will call when it’s about to suspend, to resume, to retrieve return value, to record exception, etc. Again, we’ll talk about details in future posts.

C++ coroutines usesco_await/co_returnoperators

co_await operator means “fire this async operation, suspend my code (if necessary), and resume execution with the return value”. So in this case, when calling co_await async_add(a, b), it’ll let the “expensive” add operation happen in another thread, suspend the execution, and resume the c = asignment with return value, and proceed with next execution. The async operation itself needs to return a awaitable expression. But for now, let’s simplify this to say it has to return a coroutine type. Not quite correct, but for the purpose of this tutorial, this is good enough at the moment.

co_return operator simply returns a return value to the coroutine, just like any other function. Note that for coroutines, you typically return the value type T in the coroutine type. In this case, the function signature returnsfuture<int>, so you need to return int.std::future<int>here means : I promise I’ll give you a int value in the future when I’m done.

I get it now, but how do I implement an async operation that returns a coroutine type?