What is the minimum set of actions I should do to use C++ co_await operator like C# await operator?
There is an article on cppreferense about corutines, where there is C# like class task<> which is used as return type, but I can't find it in standard library. When function return void, this predictably leads to a compile error.
taskin that case is just a placeholder for the plumbing you put together yourself.From https://en.cppreference.com/w/cpp/language/coroutines
When you use
co_*in your code you need to#include <coroutine>. The compiler will do stuff to your function. Example:The above code results in the following error:
Whatever the compiler is doing, it is looking for a
promise_typebut it cannot find it.To get past this we need to introduce the following code.
The return type of the
csp_awaitfunction is changed to use ourtasktype which results in a different error:So we add some more stuff
The next thing to do is to make the
sendfunction of thebidirectional_channelcoroutine friendly. It is currently a blocking function with the return typevoidwhich cannot be used as is.send_async_awaiteris our awaitable, coroutine friendly type.send_asyncis just what thesendfunction would need to be changed into to be awaitable. This code compiles but it doesn't do anything.I don't want to make this about CSP but I need to go into a little bit of detail about what needs to happen in the channel send function. In this example I'm using an unbuffered channel which should suspend until there is a ready receiver. Assuming the receiver isn't ready to begin with we need to park the send operation somewhere. To do this we need to only consider
await_readyandawait_suspend.await_readyis returning false, so the next thing to happen will beawait_suspend. we get a generic handle to our coroutine that we can use to park it.The implementation of
bidirectional_channelthat I started out with is based on threads. It uses a mutex and conditional variables to wake up blocked threads but I don't think abidirectional_channel_asynctype should be implemented in the same way. Instead, I'm going to consider an invasive approach where the suspended coroutine is parked inside the channel. I think this makes sense because this is where I later need to be able to find a parked coroutine to resume when the receiver is ready. It also implies that we could write a completely single threaded CSP library that use cooperative instead of preemptive multithreading. I think adding parallelism to this async CSP library would be easier than going the other way.I didn't go into all the details of everything here but it's a start. I'm kinda glad that it is decoupled like this because you can build whatever you think is best on top of this.