Edit: this gets support, so I would like to add clarification for posterity. This is not the best way to solve this problem - you will never want to do it manually. Consolidated user threads are nice and can be used to implement smart things like coroutines, but if you want to do this, you should use a library like libcoroutine which handles the hairy bits for you. However, although this is not a practical solution, it still presents an interesting idea and provides an interesting example of the planning and limitations of pure C99.
This is a bad answer. However, it is platform independent and, in addition, uses only the functions defined in the C99 standard.
On the other hand, it starts the CPU (there are no sleep functions in C99, so we have to wait to wait), uses what I can call magic to reserve space on the stack and completely abuse setjmp . It even uses global variables! And yet it works.
This method is called cooperative user flows, also called fibers. I applied this, as I mentioned, using setjmp and longjmp . context_switch performs simple Round Robin scheduling.
This is the code:
#include <stdio.h> #include <setjmp.h> #include <time.h> static jmp_buf jmp[2]; static int cur; void context_switch() { /* sleep(1) */ /* C99 doesn't have any sleeping functions */ if (!setjmp(jmp[cur])) { if ((sizeof(jmp)/sizeof(*jmp)) == ++cur) cur = 0; longjmp(jmp[cur], 1); } } void fun2() { char cushion[1000]; /* reserve some stack space */ time_t old_time, new_time; cushion[0] = '@'; /* don't optimize my cushion away */ old_time = time(NULL); cur = 1; /* the first thread to context switch is this one */ setjmp(jmp[1]); while (1) { context_switch(); new_time = time(NULL); if ((new_time - old_time) > (2 * 60)) { old_time = new_time; printf("Printed every 2 minutes\n"); } } } void fun1() { char cushion[1000]; /* reserve some stack space */ time_t old_time, new_time; cushion[0] = '@'; /* don't optimize my cushion away */ if (!setjmp(jmp[0])) fun2(); old_time = time(NULL); while (1) { context_switch(); new_time = time(NULL); if ((new_time - old_time) > (1 * 60)) { old_time = new_time; printf("Printed every 1 minute\n"); } } } int main(int argc, char **argv) { fun1(); return 0; }
And this is the result that I get:
$ gcc -ggdb -std=c99 -o silly silly_setjmp.c $ ./silly Printed every 1 minute Printed every 2 minutes Printed every 1 minute Printed every 1 minute ...
cha0site
source share