
On Fri, Oct 10, 2008 at 3:50 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Another solution is coroutines, which allows to return data then reenter later in the same context and keep going. The results of a coroutine can then be iterated as they come, giving the advantages of smart iterator/ranges while keeping the syntax of output iterators. It is however at the cost of some stack allocation at the beginning (which can be improved using pools) and context switches at each iteration.
Stack switching can be amortized by buffering more than one data for every context switch. The consumer can no longer control the exact amount of data produced by the producer but in many cases it doesn't matter.
What I propose is thus to make an output iterator that will yield the data within a coroutine context. With that solution, one writes generators as functions writing to output iterators, but those iterators might as well be writing to containers than actually yielding the result, which means the person designing the generator does not have the overhead of coroutines forced upon him.
<SNIP> In fact I have been planning for a long time to make the 'self' type be a functor. The interface to yield a value would change from the current: template<Self> my_result my_gen(Self& f) { for(....) self.yield(val); self.exit(); } to: template<F> void my_gen(F f) { for(...) f(val); } (note the switch from pass by reference to pass by value) Making an output iterator from 'f' is trivial via boost::function_output_iterator.
The coroutine GSoC library from 2006 does offer that kind of thing, but not as non-intrusive output iterators. (I don't even get why it needs to call self.__self_exit__() at the end).
For no reason: at that time I thought it would have been a good idea to require the generating function have a result type equal to the coroutine yield-type, so that I could statically check it. Unfortunately this means you have to use 'return' instead of 'yield' to yield the last value of the generation, or exit via an exception (generated by self.exit()). It was just stupid and I will to remove it. Btw, the same thing can be done with the current interface with a trivial wrapper around the generating function.
By the way, what is the status of that library? I haven't heard of it for quite a while.
Real life (and a job) got in the way. Progress has since been slow. -- gpd