CppCon 2015: Gor Nishanov “C++ Coroutines - a negative overhead abstraction'

preview_player
Показать описание


C++ coroutines are one of the few major features that may land in C++17. We will look at the current standardization status, available experimental implementations and develop a small coroutine adapter over raw C networking APIs that will beat hand-crafted state machine in performance.

Gor Nishanov is a is a Principal Software Design Engineer on the Microsoft C++ team. He works on the 'await' feature. Prior to joining C++ team, Gor was working on distributed systems in Windows Clustering team.


*-----*
*-----*
Рекомендации по теме
Комментарии
Автор

In all seriousness, I can't wait for this feature to land. It will be amazing. Thank you, Python for reminding us how great it is to yield.

allyourcode
Автор

Coroutine allows to code up a state machine as an imperative control flow. Without coroutines, you just have to implement the state machine by hand.

re: fundamental
Yes, in C++ we are attempting to do coroutines as generalized functions, as opposed to just specific applications of coroutines, such as generators or async functions that are available in other languages.

GorNishanov
Автор

Every coroutine only requires as much memory as needed for the local variables that persist across suspends plus about 2 pointer sized values. They execute on the existing stack. Coroutine frame is kept on the side. Search for the last year CppCon presentation: Await 2.0 and look at slides 4 and 5.

GorNishanov
Автор

@1:12 I love the one guy in the audience who claps. He is the only person in the audience with good taste.

allyourcode
Автор

Great talk. The slide at 6:30 explains it all, excellent.

YourCRTube
Автор

Very cool. Have used coroutines in a few languages, looking forward to simplifying some of my C++ code.

jjurksztowicz
Автор

All the design changes proposed in P0054 were approved including await_transform. The coroutine wording goes through the core language review. If the core is satisfied with wording, in February 2016 meeting, there will be a motion to move it to C++17 or to delay it and put it into TS. Which motion succeeds I do not know.

GorNishanov
Автор

There is an overview doc which is now is a little bit stale (some names have changes) search for N4402.pdf.

The latest wording P0057R1 will be published next week. You can find the previous version by searching for P0057R0.pdf

GorNishanov
Автор

Thank you Gor. Excellent work, looking forward to adding support to stackless coroutines in our company concurrency library.

massimotristano
Автор

I didn't see the details of implementation spelled out but for a basic generator function that does yield (like very first example) it should be pretty easy to do in the compiler: just make the generator function allocate its stack frame in the dynamic memory but call whatever other functions using the normal stack. This frame would contain all the state that needs to be preserved through the yields. Of course the dynamic memory doesn't have to be dynamic as such, it it's scope is within a parent function, the frame can be allocated directly inside the parent's stack frame. But there still will be the distinction of this stack frame being not contiguous with the stack used for the calls of othe rfunctions from the generator. And from the answers to the questions, it looks like that's what you're doing?

If yield would be allowed to be called from sub-functions, that's more difficult, it would require all the functions (at least within the path between the root of the call tree at the generator and the nodes that may use yield) to use the dynamically allocated stack frames. But I'm not sure if anyone needs it, and I think Python doesn't allow it.

The real dynamic allocation would be still useful to implement in a reasonable way the things like the Universal Driver Interface from years before.

sergeybabkin
Автор

I would have liked to also have benches of a Boost.Coroutines based implementation. In this talk, it is claimed that this implementation is faster than Boost's; is there published figures that demonstrate it?

AkimDemaille
Автор

One scalability problem i see is the required stacksize for tens of thousands of coroutines. I was using coroutines via setjmp before and this has always been a problem. Do we finally have non contingoues stacks like GO ?

llothar
Автор

Anyone knows what flag to pass to the compiler to accept Gor's hello world example?

massimotristano
Автор

The opening _hello_ example will not work in the final standard. Besides changing the keyword from yield to co_yield, the standard prohibits `auto` deduced return types on a coroutine.

JohnDlugosz
Автор

is there any progress in bringing coroutines to c++?

Abdalic
Автор

After watching the presentation, It seems to me (as COBOL programmer :)) that coroutines are something fundamental (as functions) and that new coming TSs like Range TS or Concurrency TS should be implemented on top of coroutines. For example, in Ranges, yielding an element of a lazy sequence. I wonder how did they implement this kind of things without coroutines now?

Abdalic
Автор

Thanks, that made it a bit more clear, and i guess i will fully understand it after playing with it.

Besides the raw language feature can we expect a few std libraries coming with C++17 already using it in real world useable scenarios (aio/networking looks promising) ?

llothar
Автор

We do this in Ruby all the time. :p
Seriously, I do wish this was a part of C++17. It is not. Maybe C++20?

friedrichdergroe
Автор

I am so sick of getting excited for cpp features only to have to wait half a decade to see anything; it's depressing.
maybe c++36 will have coroutines, proper ranges, modules and concepts used in stl
maybe ill be dead by then

TheBlenderblob
Автор

On question. In this examples when doing IO, I don't understand what is driving switching to a IO coroutine to retry the operation. What I mean: the IO (eg. TCP socket) is not ready, so coroutine suspends and yields back to caller. Now when exactly is it going to get called again? Is it supposed to be program-wide polling (retry until succeed), or integration with a OS-level event loop is necessary?

ddddddddd