|
| 1 | +/* |
| 2 | + * Test code for Protothread implementation. |
| 3 | + * |
| 4 | + * This is based on Adam Dunkel's Protothreads. |
| 5 | + * |
| 6 | + */ |
| 7 | + |
| 8 | +#ifndef __PT_H__ |
| 9 | +#define __PT_H__ |
| 10 | + |
| 11 | +#define FEP_2(WHAT, WHAT_LAST, X, Y) WHAT_LAST(X,Y) |
| 12 | +#define FEP_4(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_2(WHAT, WHAT_LAST, __VA_ARGS__) |
| 13 | +#define FEP_6(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_4(WHAT, WHAT_LAST, __VA_ARGS__) |
| 14 | +#define FEP_8(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_6(WHAT, WHAT_LAST, __VA_ARGS__) |
| 15 | +#define FEP_10(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_8(WHAT, WHAT_LAST, __VA_ARGS__) |
| 16 | +#define FEP_12(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_10(WHAT, WHAT_LAST, __VA_ARGS__) |
| 17 | +#define FEP_14(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_12(WHAT, WHAT_LAST, __VA_ARGS__) |
| 18 | +#define FEP_16(WHAT, WHAT_LAST, X, Y, ...) WHAT(X,Y)FEP_14(WHAT, WHAT_LAST, __VA_ARGS__) |
| 19 | + |
| 20 | +#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,NAME,...) NAME |
| 21 | +#define FOREACH_PAIR(action, ...) \ |
| 22 | + GET_MACRO(__VA_ARGS__,FEP_16,OOPS15,FEP_14,OOPS13,FEP_12,OOPS11,FEP_10,OOPS9,FEP_8,OOPS7,FEP_6,OOPS5,FEP_4,OOPS3,FEP_2,OOPS1,)(action,action,__VA_ARGS__) |
| 23 | +#define FOREACH_PAIR_LAST(action, action_last, ...) \ |
| 24 | + GET_MACRO(__VA_ARGS__,FEP_16,OOPS15,FEP_14,OOPS13,FEP_12,OOPS11,FEP_10,OOPS9,FEP_8,OOPS7,FEP_6,OOPS5,FEP_4,OOPS3,FEP_2,OOPS1,)(action,action_last,__VA_ARGS__) |
| 25 | + |
| 26 | + |
| 27 | +typedef void *pt_context_p; |
| 28 | + |
| 29 | +#define PT_TERMINATE (0) |
| 30 | +#define PT_RESUME (1) |
| 31 | + |
| 32 | +#define PT_MAKE_FUNC_ARG(T,V) PT_MAKE_FUNC_ARG_1(T,V) |
| 33 | +#define PT_MAKE_FUNC_ARG_1(T,V) T V, |
| 34 | +#define PT_MAKE_FUNC_ARG_LAST(T,V) PT_MAKE_FUNC_ARG_LAST_1(T,V) |
| 35 | +#define PT_MAKE_FUNC_ARG_LAST_1(T,V) T V |
| 36 | +#define PT_MAKE_STRUCT_FIELD(T,V) PT_MAKE_STRUCT_FIELD_1(T,V) |
| 37 | +#define PT_MAKE_STRUCT_FIELD_1(T,V) T V; |
| 38 | +#define PT_MAKE_ARG_ASSIGN(T,V) PT_MAKE_ARG_ASSIGN_1(T,V) |
| 39 | +#define PT_MAKE_ARG_ASSIGN_1(T,V) pt_args->V = V; |
| 40 | + |
| 41 | +#define PT_CONCAT(A,B) PT_CONCAT_1(A,B) |
| 42 | +#define PT_CONCAT_1(A,B) A##B |
| 43 | + |
| 44 | +#define PT_FUNC(name, ...) \ |
| 45 | +struct PT_CONCAT(pt_args_,name) { \ |
| 46 | + FOREACH_PAIR(PT_MAKE_STRUCT_FIELD,__VA_ARGS__) \ |
| 47 | +}; \ |
| 48 | +static int PT_CONCAT(pt_func_,name)(void *args_arg, void **ctx_arg); \ |
| 49 | +int name(FOREACH_PAIR_LAST(PT_MAKE_FUNC_ARG, PT_MAKE_FUNC_ARG_LAST, __VA_ARGS__)) {\ |
| 50 | + struct pt_args_##name *pt_args = calloc(1, sizeof(struct pt_args_##name)); \ |
| 51 | + if(!pt_args) return -1; \ |
| 52 | + FOREACH_PAIR(PT_MAKE_ARG_ASSIGN,__VA_ARGS__) \ |
| 53 | + return pt_schedule(PT_CONCAT(pt_func_,name),pt_args); \ |
| 54 | +} \ |
| 55 | +int PT_CONCAT(pt_func_,name)(void *args_arg, void **ctx_arg) { \ |
| 56 | + struct PT_CONCAT(pt_args_,name) *args = (struct PT_CONCAT(pt_args_,name) *)args_arg; |
| 57 | + |
| 58 | +#define PT_CONTEXT(...) \ |
| 59 | + struct pt_ctx { \ |
| 60 | + int pt_state; \ |
| 61 | + FOREACH_PAIR(PT_MAKE_STRUCT_FIELD,__VA_ARGS__) \ |
| 62 | + } *ctx = (struct pt_ctx *)(*ctx_arg); \ |
| 63 | + if(!ctx) { \ |
| 64 | + ctx = calloc(1, sizeof(struct pt_ctx)); \ |
| 65 | + if(!ctx) return PT_TERMINATE; \ |
| 66 | + *ctx_arg = ctx; \ |
| 67 | + } |
| 68 | + |
| 69 | +#define PT_BODY \ |
| 70 | + switch(ctx->pt_state) { \ |
| 71 | + case 0: |
| 72 | + |
| 73 | +#define PT_EXIT \ |
| 74 | + do { ctx->pt_state = 0; return PT_TERMINATE; } while(0) |
| 75 | + |
| 76 | +#define PT_END \ |
| 77 | + default: \ |
| 78 | + break; \ |
| 79 | + } \ |
| 80 | + PT_EXIT; \ |
| 81 | +} |
| 82 | + |
| 83 | +#define PT_YIELD ctx->pt_state = __LINE__; return PT_RESUME; case __LINE__: do {} while(0) |
| 84 | +#define PT_WAIT_WHILE(cond) do {ctx->pt_state = __LINE__; case __LINE__: if((cond)) return PT_RESUME; } while(0) |
| 85 | +#define PT_WAIT_UNTIL(cond) do {ctx->pt_state = __LINE__; case __LINE__: if(!(cond)) return PT_RESUME; } while(0) |
| 86 | + |
| 87 | + |
| 88 | + |
| 89 | +#endif |
0 commit comments