Created
April 19, 2015 12:00
-
-
Save mintisan/4a3b599b559ae82194e3 to your computer and use it in GitHub Desktop.
Tony Finch - Coroutines in less than 20 lines of standard C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* From | |
* http://fanf.livejournal.com/105413.html | |
**/ | |
#include <stddef.h> | |
#include <setjmp.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#define MAXTHREAD 5 | |
static void *coarg; | |
void *coto(jmp_buf here, jmp_buf there, void *arg) { | |
coarg = arg; | |
if (setjmp(here)) return(coarg); | |
longjmp(there, 1); | |
} | |
#define STACKDIR - // set to + for upwards and - for downwards | |
#define STACKSIZE (1<<12) | |
static char *tos; // top of stack | |
void *cogo(jmp_buf here, void (*fun)(void*), void *arg) { | |
if (tos == NULL) tos = (char*)&arg; | |
tos += STACKDIR STACKSIZE; | |
char n[STACKDIR (tos - (char*)&arg)]; | |
coarg = n; // ensure optimizer keeps n | |
if (setjmp(here)) return(coarg); | |
fun(arg); | |
abort(); | |
} | |
static jmp_buf thread[MAXTHREAD]; | |
static int count = 0; | |
static void comain(void *arg) { | |
int *p = arg, i = *p; | |
for (;;) { | |
printf("coroutine %d at %p arg %p\n", i, (void*)&i, arg); | |
int n = arc4random() % count; | |
printf("jumping to %d\n", n); | |
arg = coto(thread[i], thread[n], (char*)arg + 1); | |
} | |
} | |
int main(void) { | |
while (++count < MAXTHREAD) { | |
printf("spawning %d\n", count); | |
cogo(thread[0], comain, &count); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Result: