/
coroutines.h
74 lines (66 loc) · 4.37 KB
/
coroutines.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#ifndef __COROUTINES_H__
#define __COROUTINES_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct CoroutineState CoroutineState;
struct CoroutineState {
void *state; /* Pointer to a struct representing the internal state
of the coroutine. We need this since we have to
reinstate the scope whenever the function is
re-intered. */
long current; /* The line number of where the coroutine should
return. Used in 'yield' and 'recur' */
unsigned char done; /* A marker to show that a recurrence is completed */
CoroutineState *next; /* The next in the stack of states */
CoroutineState *parent; /* NULL if actually the parent, pointer otherwise */
CoroutineState *tail; /* Only the parent is guaranteed to know the tail */
};
CoroutineState* createCoroutineState() {
CoroutineState *s = (CoroutineState*) malloc(sizeof (CoroutineState));
bzero(s, sizeof(CoroutineState));
return s;
}
#define initializeCoroutineState(coroutineState, UserStateType, userStateVar) \
UserStateType *userStateVar = (UserStateType*) coroutineState->state; \
switch(coroutineState->current) { \
case 0: \
if(coroutineState->state == 0) { \
coroutineState->state = (void*) malloc(sizeof (UserStateType)); \
bzero(coroutineState->state, sizeof(UserStateType)); \
} \
userStateVar = (UserStateType*) coroutineState->state; \
#define recur(coroutineState,func) \
do{ \
CoroutineState *parent = coroutineState ? coroutineState \
: coroutineState->parent; \
coroutineState->next = createCoroutineState(); \
coroutineState->next->parent = parent; \
parent->tail = coroutineState->next; \
while(!coroutineState->next->done) { \
CoroutineState *parent = coroutineState ? coroutineState \
: coroutineState->parent; \
typeof(func) tmp = func; \
coroutineState->current = __LINE__; \
if(!parent->tail->done) \
return tmp; \
case __LINE__: 1; \
} \
} while(0) \
#define yield(coroutineState, value) \
do{ \
CoroutineState *parent = coroutineState ? coroutineState \
: coroutineState->parent; \
coroutineState->current = __LINE__; \
parent->tail = coroutineState; \
free(coroutineState->next); \
coroutineState->next = 0; \
return value; \
case __LINE__: 1; \
} while(0)
#define finalizeCoroutine(s) \
} \
s->done = 1; \
free(s->next); \
s->next = 0;
#endif /*__COROUTINES_H__ */