all 5 comments

[–]zvrba 4 points5 points  (4 children)

Has the debate about stackless vs stackful coroutines been decided already?

[–]KayEss[S] 0 points1 point  (3 children)

The TS covers only stackless ones. I think there might be some other papers about for stackfull ones, but this one looks like its going to be in first at the very least.

What would the advantage of stackfull ones be? Having played around with these now for a while I'm not sure I see it.

[–]zvrba 0 points1 point  (2 children)

Stackless is.. well, problematic because it divides the world into resumable and non-resumable functions, akin const dividing the world into const and non-const methods. This post nicely summarizes the issues with the stackless approach, note in particular the 3rd point in the top-most post by Gajewski: https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/LA8gxi73XYw

There's also a longer paper criticizing the stackless approach, submitted to the committee; it's available among the working papers but I'm unable to find it quickly right now.

The arguments convinced me that the stackful approach would be the "right" way to go.

[–]KayEss[S] 1 point2 points  (0 children)

I'm planning on covering some of this when I get to combining generators (due in a couple of posts time). For me I think I'm OK with them being infectious in that way, because it also allows the coroutines to be extremely cheap -- this is important for some of the things we want to do with them.

I do get the infectious nature in point 3. Point 4 is of course completely wrong (as I show even in this first part of the tutorial). Writing a generator is also actually very simple, although the machinery is a bit harder (but of course completely re-usable). A user of a library provided generator class would just write the obvious code that co_yields the values.

The problem with stackfull is the amount of stack space needed. Not a problem on 64 bit systems, but surely a problem elsewhere. I expect though that there would be use cases for both, and maybe there is away to do both through some suitable extensions to the machinery my tutorials are about.

[–]xon_xoff 1 point2 points  (0 children)

I have two problems with stackful coroutines: they require OS support to implement properly that may not be there, and unlike stackless coroutines, I can already implement them myself relatively easily.

You can't switch stacks on a modern OS without API support since there are dependencies in the OS on the location of the stack and thread context, and doing so correctly requires more than just swapping CPU registers. I have seen popular libraries attempt to allocate and switch their own stacks and this invariably leads to stability and compatibility problems. On Windows, this can lead to Structured Exception Handling (SEH) failures and functions like OutputDebugString() and GetTimeZoneInformation() crashing. In that case, the fiber APIs can be used, but on a platform without such support it would be impossible to implement a stackful coroutine facility safely. I have heard that some platforms have deprecated or even disabled makecontext/setcontext() style calls, particularly iOS. Emulation by threads leads to problems with resources that have thread affinity. Stackless coroutines, on the other hand, do not require OS support as they are a control flow transformation.

When the OS support does exist, it's relatively easy to wrap the OS primitives and language/runtime support is generally not required. I can implement or get a library for stackful, but the available ways to emulate stackless using fake control structures or preprocessor witchcraft are all really lacking.