Since the Coroutines TS has been accepted into C++20 at the ISO meeting at Kona, I started playing around with them a bit for myself. Clang already has decent support for coroutines but the implementation of the library support is still lacking. In particular, the Awaitable types such as std::future, std::generator, etc. have not been implemented yet.
Thus, I took it upon myself to make std::future awaitable. I largely followed the talk by James McNellis at CppCon 2016, specifically this slide:
This being 2019, I actually had some trouble with the (presumably untested?) code on this slide:
- It seems to me overloading
operator co_awaitis not a thing anymore? Instead one should use the optionalawait_transformof thepromise_type. Not sure I got this right, though. - The
thencontinuation of the future captures the handle by value, but theresumemember function is not const-qualified. I worked around this by making the lambdamutable.
Also, then and is_ready are not available in std::future but are part of std::experimental::future which is still missing from my libc++ version. To avoid dealing with the Awaiter and to implement future continuations, I wrote a derived future class which is Awaitable and an Awaiter. It is my understanding that eventually both would also be true of std::future. You can see my example on Compiler Explorer. It does compile.
However, it also does segfault. This happens in await_resume when get() is called. This is actually not surprising since valid() returns false at that point (making the call to get() UB). I think this is because when then is used to continue the future, the original future object is moved into the async future, thus invalidating the old future (*this at the time await_resume is called, so after the move). My implementation of then is loosely inspired by this answer and this code I found on GitHub. Those may not be ideal, but cppreference explicitly states valid() == false as a postcondition of calling then, so I believe it is correct to move out of the original future.
What am I missing here? This "bug" seems present already in the above slide. How can I reconcile this issue? Does anybody know of a (working) existing implementation of an Awaitable future? Thanks.
