[comp.lang.c] Implementing co-routines etc.

raghavan@umn-cs.cs.umn.edu (Vijay Raghavan) (03/14/88)

     Let me make it clear that this is *not* a feature that I want
to see in D, or anything like that. I think that if co-routines
are desired, a programmer can implement them on his own in C,
with about the amount of portability that setjmp and longjmp
have. I do have such an implementation (which, of course, I've
never really had to use, except to satisfy myself that it
works.) My problem is that I don't *like* the implementation. There
is a particular bit of dirty coding which I can't seem to get
around no matter how I shift and squirm. I think that this is 
a peculiar situation where one *has* to resort to a little bit of
kludgery in order to get the job done. But maybe I'm wrong. How 
would *you* code the functions "instantiate" and "resume" to make
the following program work?

     Remember, you have to write the functions all in C, no 
assembler allowed. Of course, you may reasonably ask what the
functions are supposed to do in the first place, but I think 
the code and choice of names makes that clear. The program uses
the Sieve of Eratosthenes to generate prime numbers. Whenever a 
prime number is discovered, a new "filter" coroutine is 
instantiated, which tests whether future numbers generated by "gennum"
are multiples. You may assume that whenever *any* co-routine terminates,
so does the whole program.

---------------------------------------------- Cut here ---------------
#include <stdio.h>
#define MAXPRIMES 10000

char * handle, *instantiate();
int number = 1, primes = 0, maxprimes = MAXPRIMES;

main(argc, argv) 
int argc;
char ** argv;
{
	int gennum();

	if (argc >= 2) 
		maxprimes = atoi(argv[1]);
	handle = instantiate (gennum);
	resume (handle);
}

gennum() {
	int filter();
	char * filterhandle = instantiate(filter);

	for(;;) {
		++ number; 
		resume (filterhandle);
	}
}

filter() {
	int mine; 
	char * myfilter = NULL;

	primes ++;
	printf ("Prime #%d is %d\n", primes, mine = number);
	while (primes < maxprimes)
		if (number % mine) {
			if (myfilter == NULL)
				myfilter = instantiate (filter);
			resume (myfilter);
		}
		else
			resume (handle);
}		
------------------------------ Cut here -------------------------

Vijay Raghavan

edk@gryphon.CTS.COM (Ed Kaulakis) (03/20/88)

In article <4326@umn-cs.cs.umn.edu>, raghavan@umn-cs.cs.umn.edu (Vijay Raghavan) writes:
> 
>      Let me make it clear that this is *not* a feature that I want
> to see in D, or anything like that. I think that if co-routines
> are desired, a programmer can implement them on his own in C,
> with about the amount of portability that setjmp and longjmp
> have. I do have such an implementation (which, of course, I've
> never really had to use, except to satisfy myself that it
> works.) My problem is that I don't *like* the implementation. There
> is a particular bit of dirty coding which I can't seem to get
> around no matter how I shift and squirm. I think that this is 
> a peculiar situation where one *has* to resort to a little bit of
> kludgery in order to get the job done. But maybe I'm wrong. How 
> would *you* code the functions "instantiate" and "resume" to make
> the following program work?
> 

	Well, my opinion is that it can't be done in pure C, which doesn't
know anything about its own stack pointer. The stack pointer *must* be 
manipulated to give a coroutine the same kind of syntactic sugar on offset
references to its activation record (a mechanism often thought of as "auto"
variable allocation) that is enjoyed by regular C functions. Thus any 
coroutining code must kludgily mess with a hardware thingy that's not 
even declarable, for bizarre side-effect.