Created
July 26, 2010 21:45
-
-
Save jsn/491302 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
*.o | |
main | |
tags |
This file contains hidden or 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
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <setjmp.h> | |
#include "coro.h" | |
struct state { | |
struct state *next, *prev ; | |
jmp_buf jmp ; | |
void *saved, *start ; | |
size_t len, used ; | |
} ; | |
static int stack_dir ; | |
static struct state zero = {&zero, &zero}, *current = &zero ; | |
static void *cont ; | |
static int check_stack(void *p) { return (char *)&p - (char *)p > 0 ? 1 : -1 ; } | |
static int coro_save(void) { | |
void *p ; | |
if (!stack_dir) stack_dir = check_stack(&p) ; | |
current->used = abs((char *)current->start - (char *)&p) + sizeof(p) ; | |
p = stack_dir < 0 ? &p : current->start ; | |
if (current->len < current->used) { | |
if (current->saved) free(current->saved) ; | |
current->len = current->used + 512 ; | |
current->saved = malloc(current->len) ; | |
} | |
memcpy(current->saved, p, current->used) ; | |
if (setjmp(current->jmp)) { | |
memcpy(cont, current->saved, current->used) ; | |
cont = NULL ; | |
return 1 ; | |
} | |
return 0 ; | |
} | |
static void coro_restore(void) { | |
cont = (stack_dir > 0) ? | |
current->start : | |
(char *)current->start - current->used + sizeof(void *) ; | |
longjmp(current->jmp, 1) ; | |
} | |
void coro_start(coro f, int hint) { | |
if ( | |
(!current->start) || | |
((char *)current->start - (char *)hint) * stack_dir < 0 | |
) | |
current->start = &hint ; | |
if (coro_save() == 0) { | |
struct state * tmp = calloc(sizeof(*tmp), 1) ; | |
tmp->next = current ; | |
tmp->prev = current->prev ; | |
tmp->next->prev = tmp->prev->next = tmp ; | |
tmp->start = &hint ; | |
current = tmp ; | |
f(hint) ; | |
tmp->prev->next = tmp->next ; | |
tmp->next->prev = tmp->prev ; | |
current = tmp->next ; | |
if (tmp->saved) free(tmp->saved) ; | |
free(tmp) ; | |
coro_restore() ; | |
printf("notreached\n") ; | |
return ; | |
} | |
} | |
void coro_yield(void) { | |
if (coro_empty() || coro_save()) return ; | |
current = current->next ; | |
coro_restore() ; | |
} | |
int coro_empty(void) { | |
return current == current->next ; | |
} |
This file contains hidden or 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
#ifndef __CORO_H__ | |
#define __CORO_H__ | |
typedef void (*coro)(int hint) ; | |
void coro_start(coro f, int hint) ; | |
void coro_yield(void) ; | |
int coro_empty(void) ; | |
#endif /* __CORO_H__ */ |
This file contains hidden or 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
This file contains hidden or 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
#include <stdio.h> | |
#include "coro.h" | |
void f2(int hint) { | |
int i ; | |
printf("started %d\n", hint) ; | |
for (i = 0; i < hint; i ++) { | |
printf("f2: %d (%d)\n", i, hint) ; | |
coro_yield() ; | |
} | |
printf("ended %d\n", hint) ; | |
} | |
void f1(int hint) { | |
int i ; | |
for (i = 0; i < hint; i ++) { | |
coro_yield() ; | |
printf("f1: %d (%d)\n", i + 3, hint) ; | |
coro_start(f2, i + 3) ; | |
coro_yield() ; | |
} | |
} | |
int main(int ac, const char *av[]) { | |
coro_start(f1, 3) ; | |
coro_start(f2, 12) ; | |
while(!coro_empty()) coro_yield() ; | |
return 0 ; | |
} | |
This file contains hidden or 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
CFLAGS = -Wall -O3 -fomit-frame-pointer | |
OBJS = coro.o | |
HEADERS = coro.h | |
LIBS = | |
TOPLEVEL = tags main | |
all: $(TOPLEVEL) | |
tags: $(OBJS) $(HEADERS) | |
ctags *.[chl] || echo no ctags, who cares | |
main: main.c $(OBJS) | |
$(CC) $(CFLAGS) -o $@ $< $(OBJS) $(LIBS) | |
$(OBJS): $(HEADERS) | |
clean: | |
rm -f $(OBJS) $(TOPLEVEL) | |
stats: clean | |
echo `cat *.[chl] | wc -l` lines, \ | |
`cat *.[chl] | grep -v '^ *$$' | grep -v '^ */[\*/]' | wc -l` loc |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment