From: Daniel James (daniel_at_[hidden])
Date: 2005-01-10 05:14:20


Pavel Vozenilek wrote:

> It could be made even w/o threads, using some cooperative
> model of execution.
>
> Stephen Dewhurst gave example of such way in
> http://www.semantics.org/once_weakly/w11_judgement.pdf

Simon Tatham also wrote about it here:

http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

Although, he disagrees with Stephen Dewhurst's dislike of macros.

A while ago I wrote a library which did something similar for C++ and
allowed the 'coroutines' to recurse, have parameters and local variables
(which aren't easy because they have to be stored between calls and
can't be defined inside a switch statement) and be members of a class.
But I was never very happy with it, mainly because the implementation
involves some pretty messy preprocessor metaprogramming and the
coroutines had to be written using a strange macro based language, for
example, a simple 'toupper' coroutine:

   // Roughly equivalent to:
   // char toupper(std::istream& in)
   COROUTINE(toupper,
       yield(char) parameter(std::istream&, in) local(char, c))
   {
       while(in.get(c))
       {
           COROUTINE_YIELD_VALUE(std::toupper(c));
       }
   }
   COROUTINE_END

   int main()
   {
       coroutines::coroutine<char> co(toupper(std::cin));

       // Coroutines return a boost::optional which is empty
       // when the coroutine exits.
       boost::optional<char> c;

       while((c = co.resume()))
       {
           std::cout<<*c;
       }
   }

If anyone's interested I'll make the code available. I'll need to fix it
up a little first, as it currently only works on old versions of gcc,
and isn't documented.

Daniel