Boost logo

Boost :

Subject: [boost] Coroutines and Output Iterators
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2008-10-10 09:50:19

When one wants to generate some range of data, the usual approach is to
write the data to some output iterator passed as an argument.

However, that approach has a few drawbacks: it is necessary to provide a
range (often of a non-known size) to write the data on, and it will be
possible to consider that data only once all elements have been copied
to the output.

An alternative approach is returning a smart range which will generate
the elements as it is being iterated. It is somewhat what the
Boost.Range update in the review queue does.
This approach has many advantages, since storage may not be needed and
transformations can be combined on top, avoiding unnecessary iterations.

Writing smart iterators/ranges that generate data, though, is much more
difficult than writing generators using the previous solution,
especially in recursive scenarios where the iterators will need to
maintain a stack themselves.

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.

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.

The syntax would be
generate(boost::bind(&boost::transform, range, _1, f)) which would
return a range similar to that of boost::make_transform_range(range, f).
(boost::transform being just std::transform for ranges)

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).
I thus propose a simple output iterator that yields on iteration be made.

By the way, what is the status of that library? I haven't heard of it
for quite a while.

Boost list run by bdawes at, gregod at, cpdaniel at, john at