
On 5/6/06, Giovanni P. Deretta <gpderetta@gmail.com > wrote:
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.
I see. A free yield may be not so bad, for most operating systems support retrieving current coroutine:-) Besides, what is the return type of "yield"? In the document I see tie(parm_1, parm_2,... parm_n) = self.*yield*(result_1, result_2,... result_n); I guess it should just return an integer or something else, not a real tuple, right? If the point is to check the return type, maybe we can trick the compiler like this: int __yield(T); #define yield(val) if (__yield(val) < 0) return val; If the return value of __yield should not be less than 0, the compiler would check the type of "val" automatically.
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.
What confused me is that coroutine::operator(...) takes parameters. Does this mean the parameters of a coroutine can be bound at either creation time or invocation time or both? It seems that coroutine::operator () mixes the responsibilities of both binding and resuming, which should be separated, in my opinion. Any way, I will modify the pseudocode examples to conform to a single
interface.
Thanks for the feedback.
-- Giovanni P. Deretta _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost