
Xi Wang wrote:
It looks great. I still don't catch why there must be a "self" as the first parameter in a coroutine definition. Could the "current" function help here? If removed, the "yield" function would be much easier to use.
The coroutine return type is statically defined. Thus yield (that is both a form of return and call) must know the return type and the argument types. The only way to statically type check these types is to make yield a member of the coroutine or take the coroutine as a parameter. In both cases the coroutine needs a pointer to itself. A current coroutine global pointer would necessarily erase all type informations, and a global yield function that uses this pointer would need to delay all checking until runtime. This would both slow down yielding and prevent the compiler from checking error a compile time. Note that in the "Other Issues" section there is a mention of a free yield function that uses the current_coroutine pointer. But this wouldn't be the prefered interface, if it is implemented at all.
Another question is, does a "coroutine" object act as both a coroutine instance and a coroutine factory? According to the examples it seems that sometimes a coroutine binds data when created, and sometimes a coroutine uses operator () to create a new instance, right?
Probably I should mark more clearly the pseudocode examples where I make liberal use of the coroutine keyword both to create new instances and to mark a coroutine body) and actual C++ code. In C++, a coroutine object *always* represent a single instance. The constructor binds the coroutine with the function object that implement the body. coroutine::operator(...) resumes (or start, if not already started) the specific coroutine instance to which is applied. Any way, I will modify the pseudocode examples to conform to a single interface. Thanks for the feedback. -- Giovanni P. Deretta