Coroutines in C

Bill Poser poser at csli.Stanford.EDU
Thu Aug 17 07:43:05 AEST 1989


In article <5710 at ficc.uu.net> peter at ficc.uu.net (Peter da Silva) writes:
>Generators in 'C'... I guess you could use coroutines to implement
>something like Icon generators, but Smalltalk generators might be
>easier. There's more to Icon generators than the function itself...
>how do you do !every write(factor(192))!?

It seems to me that this question confuses implementation of generators,
that is, having multiple calls to factor() return the several factors,
and goal-oriented evaluation, where the "every" construct (as well
as others, some implicit) causes write() to be called until it fails
which in turn causes factor() to be called until it fails, which happens
when it runs out of results to return. Goal-oriented evaluation
a la Icon does indeed require more than saving stack frames, but
implementing the generator itself doesn't.

>Generators in Smalltalk are implemented differently than in Icon.
>You set up methods for getting the first and next element of the
>sequence, and use instance variables (if necessary) to maintain
>state. This is more conventional, and wouldn't require coroutines.

I'm not sure I understand how this solves the problem. Using instance
variables is pretty much like using statics in C to store the state
information, but the real problem is in implementing the method for
getting the next element in the sequence. It is that method that
is going to need the state information, and when the control structure
gets even moderately complicated, saving the state information without
saving the whole stack frame gets to be a pain.

For example, here is a generator that returns pointers to strings
matching a given regular expression. The array commands contains
structures whose name member is a character pointer. comcnt is the
number of array elements.

char *
AproposBuiltins(re)
regexp *re;
{
   static int i = 0;
   char *retval;

   while(i < comcnt){
      if(regexec(re,retval = commands[i].name)){
	 ++i;
	 return(retval);
      }
      else ++i;
   }

   /* If we get here there are no more matches */

   i = 0;			/* Reset for next search */
   return((char *) 0);
}

We make the loop index static and we also have to complicate the
control structure a bit over a simple loop traversal, but it
isn't too bad. How about traversing a two dimensional array?
We would not only have to make both array indices static,
but we would have to keep track of whether it was time to increment
the outer loop index or whether we should reenter the inner loop
right away. But if we save the stack frame, including not only the
auto variables but the program counter, we have all the information
we need no matter how complex the control structure.

What is similar to coroutine support is language support for the
equivalent of the Icon "suspend" primitive, which returns a value
but saves the stack frame. To my (limited) knowledge, Smalltalk
does not provide support for this. Isn't the Smalltalk method
of implementing generators just doing it by hand as in the above
C example, with instance variables playing the role of statics?



More information about the Comp.lang.c mailing list