6
votes

Why will coroutines (as of now in the newest drafts for C++1z) be implemented as a core language feature (fancy keywords and all) as opposed to a library extension?

There already exist a couple of implementations for them (Boost.Coroutine, etc), some of which can be made platform independent, from what i have read. Why has the committee decided to bake it into the core language itself?

I'm not saying they shouldn't but Bjarne Stroustrup himself mentioned in some talk (don't know which one any more) that new features should be implemented in libraries as far as possible instead of touching the core language.

So is there a good reason to do so? What are the benefits?

3
I don't know, how boost:coroutines work and if they offer the same semantics, but my guess is that coroutines can be implemented much more efficiently as a language feature than a library feature. Also, I'm not quite sure if coroutines can actually be implemented using only standard c++ at all. - MikeMB
@MikeMB : Correct on all accounts. - ildjarn
Another reason could be that it's just way way nicer as part of the language (e.g. not having to include special headers or pass special types as parameters to functions) - RamblingMad
I believe the argument Gor Nishanov from Microsoft made, is that as a compiler feature it generates less code/is more efficient. Basically in his video (linked in my answer) he talks about how really they are generalizing functions such that they can return early.. He gives some performance metrics in the video as well. The context switch will cause a cache miss, but for network code, it probably doesn't matter. - Atifm

3 Answers

8
votes

While there are library implementation of coroutines, these tend to have specific restrictions. For example, a library implementation cannot detect what variables need to be maintained when a coroutine is suspended. It is possible to work around this need, e.g., by making the used variables explicit in some form. However, when coroutines should behave like normal functions as much as possible, it should be possible to define local variables.

I don't think any of the implementers of Boost coroutines thinks that their respective library interface is ideal. While it is the best which can be achieved in the currently language, the overall use can be improved.

7
votes

At CppCon 2015, Gor Nishanov from Microsoft made the argument that C++ Coroutines can be a negative overhead abstraction. The paper from his talk is here.

If you take a look at his example, the ability to use a coroutine simplified the control flow of the network code, and when implemented at the compiler level gives you smaller code that has twice the throughput of the original. He makes the argument that really the ability to yield should be a feature of a C++ function.

They have an initial implementation in Visual Studio 2015, so you can give it a try it out for your use-case and see how it compares to the boost implementation. It looks like they are still trying to hash out if they will use the Async/Yield keywords though, so keep an eye on where the standard goes.

The resumable functions proposal for C++ can be found here and the update here. Unfortunately, it didn't make it into c++17, but is now a technical specification p0057r2. On the upside, it looks like their is support in clang with the -fcoroutines_ts flag and in Visual Studio 2015 Update 2. The keywords also have a co_ prepended to them. So co_await, co_yield etc.

Coroutines are a built in feature in golang, D, python, C#, and will be in the new Javascript standard(ECMA6). If C++ comes up with a more efficient implementation, I wonder if it would displace golang adoption.

3
votes

resumable functions from C++1z support stackless context switching, while boost.coroutine(2) provide stackfull context switching.

The difference is that with stackful context switching the stack frames of function called within the coroutine remain intact on suspending the context, while the stack frames of sub-routiens are removed on suspending a resumable fucntion (C++1z).