This release is the result of the community’s work over the past six months, including: C++17 support, co-routines, improved optimizations, new compiler warnings, many bug fixes, and more.
The release notes contain more details.
This release is the result of the community’s work over the past six months, including: C++17 support, co-routines, improved optimizations, new compiler warnings, many bug fixes, and more.
The release notes contain more details.
I’m a bit disappointed that we’re going to be stuck with stackless coroutines. You have to wonder what’s the point of having billions of coroutines if you can’t suspend at a deeper stack level.
I was surprised when I read that as LLVM can support almost any type of co-routines given that it is a pretty flexible design.
But then it became clear that LLVM is now released as a package together with CLANG. Yeah.
So if you don’t like the C++ limitations use another language – problem solved. Or you could implement your own kind unless C++ is even more fucked up since I last looked at it.
Not to worry, since Boost has stackful coroutines, and now fibers and channels that are implemented similarly to stackful coroutines. I’ve been using coroutines for async stuff and it works a treat, so C++ is not limited in that regard. It’s just that stackful coroutines won’t be standard or have a nicer syntax.
But then you’re using Boost, a poorly designed, poorly tested, poorly implemented, inconsistent, gigantic library, which tries to be robust but isn’t, tries to be header-only but isn’t, and goes to ridiculous lengths to smooth over what are, in reality, small differences between OSes.
Opinion much?
No. Most of the “ridiculous lengths” is to implement things that run across a vast number of compilers at different standards compliance levels, which happen to be across different OSes. The difference between these platform specific compilers can be huge.
kwan_e,
Well, if it gives you a problem, you can always fix it by forking it by yourself
…ok, this CS joke didn’t exactly warrant a post, but there it is, haha.
On a serious note, I haven’t looked into it yet but it seems like that would make this feature highly incompatible with other core C++ features like template metaprogramming and even trivial accessor functions to provide OOP encapsulation
Coroutines are pretty powerful, even if they are stackless: https://www.youtube.com/watch?v=EVGenON6p9g , and they don’t conflict with templates or OOP at all. Enhances* it, really, since the details of async don’t need to leak out of a function, let alone an object.
The stackless thing just means if you want to have a lot of suspend points in your coroutine, they have to occur at the base stack frame, making them not composable.
Depending on your way of thinking, it could be a good thing. Some people hate things that are too powerful/new/unfamiliar and would prefer crippled implementations of things.
* “Enhances? Fancy word for a sellcode”
kwan_e,
Sounds political
Only, like I said, if you want to suspend a coroutine in a nested stack frame. Stackless means it doesn’t have its own stack, not that it doesn’t use a stack. As I understand it, it uses the “main stack” when it is resumed. Between two “co_yield”s, it can use all the stack it likes. When it arrives at the next co_yield at the base stack level, the function’s state is saved, and another coroutine (or the main function) takes its place.
This just makes these style of coroutines non-composable in the way that stackful coroutines are (eg, cooperative, program controlled, multitasking).
Edited 2017-09-08 15:16 UTC
Yes obviously it uses a stack, this paper outlines two classes of coroutines, those that support normal stack frames and those that do not.
http://cpp.mimuw.edu.pl/files/await-yield-c++-coroutines.pdf
I suspect the boost implementation allocates a full stack for each coroutine, in which case it would share the same memory overhead as threads, but without the overhead of context switching.
Stackless technically also allocates a stack, however it only allocates memory for a single stack frame. As with traditional event oriented programming, this is very compact compared with threads.
In theory a hybrid approach would be possible such that a coroutine could effectively yield from within recursive calls so long as the caller declared it’s intentions to be yieldable, however it would seem that they didn’t implement this in C++.
I think there was a proposal that would just have the compiler analyze and decide whether to use stackful or stackless but it probably didn’t make it in time.* But from what I’ve read, there hasn’t been a successful attempt to emulate stackful coroutines with stackless.
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4398.pdf
kwan_e,
I don’t really know if anyone’s implemented it under a real compiler, but it’s actually pretty straitforward in principal. While stacks are normally linear structures, there’s no technical reason that they have to be. A trivial implementation would take each and every stack frame from the heap rather than a linear stack.
Pascal supports parent variable scoping, which may depend on having a linear stack, but C doesn’t support this, they only way to access the variables of a caller is for them to be passed in through a pointer, which makes the relationship between stack frames irrelevant.
The implementation of C++ exceptions would have to change, but it would just have to walk the stack frames via pointers rather than manipulating address offsets.
This would work transparently to the code. However due to overhead costs we probably wouldn’t want to use it globally. This is why I thought it would be good to allow the programmer to request it explicitly.
Edited 2017-09-08 18:42 UTC
That’s what the segmented stack coroutines from Boost are. They take advantage of gcc’s split stack support. So stackless coroutines that are chained together to create a stackful coroutines may as well just have been complete stackful coroutines in the first place. It would be less overhead, in terms of runtime and syntax/annotation, than emulating with stackless coroutines.
kwan_e,
It makes you wonder why the C++ standard won’t support it.
I think it’s just a matter of having a more complete proposal + compiler implementation. By that, I mean the author of the stackless coroutine proposal has implemented a form of it in Clang which shows its ability to optimize away coroutines, and the allure of having potentially billions of coroutines.
kwan_e,
Yes I realize that eliminating the full stack makes it far more scalable. I’ve been a proponent of this model for a long time. My point was that they could have supported inner coroutines also without causing any additional overhead whatsoever for code that doesn’t use it and it would have been much more flexible with regards to the algorithms one could use with it.
Consider that very frequently programmers are encouraged to break up functions for non-technical readability / aesthetic / code design reasons, but artificial language limitations on stack frames like this will force developers to compromise on where we can put code just to work around the language’s limitations, so I’m agreeing with your original post.