On Sat, 24 Sep 2016 11:49:24 -0400, Nick Sabalausky wrote: > My understanding is that C#'s coroutines, under the hood, work the same > way as C's Protothreads library:
You mean async/await, which is a compiler-provided CPS transformation on top of the Task API. There was a coroutine library for Mono, based on Mono.Tasklets, but I haven't been able to get Mono.Tasklets to work without segfaulting the last couple times I tried. > First, only C#'s coroutines can yield, not regular functions called by a > coroutine. Because it's the continuation passing style, not a full thread of execution. That makes it moderately painful to use under normal circumstances and entirely unsuitable in other cases. For instance, I've got a project that involves simulating a large number of actors (several thousand at a minimum) within a world. If I used CPS, it would be a bit painful. I'd have to keep remembering which functions are asynchronous and which are synchronous. If I needed to turn a function asynchronous, it changes how I call it, and that effect can ripple up. And that's a maintenance problem, but at least I have a type system to help out. I also need a scripting system, which will no doubt be weakly typed (ECMAScript, perhaps), and coordinating those changes there would be a much higher cost. I also want to support people writing scripts who are not cautious about writing those scripts, who don't appreciate the technical innards that I implemented, and who will write scripts that occasionally misbehave. I want to make a pit of success for them and hopefully ensure that their scripts won't typically misbehave too badly. So the CPS transformation model is a nonstarter for me, manual or partially automated. > But about implementing it in D: > > I'm not so sure that's realistic right now. Look at Node.js and Vert.x. It's not a barrier to the market to force programmers to manually execute the CPS transformation. Fibers are more convenient. They also have a large, upfront cost, but they have the advantage of treating the stack like a stack. It breaks fewer assumptions about performance. Go's multitasking is a middle ground -- it has stacks that can shrink and grow, but the cost is a check for the stack bottom at every function call.
