diff options
Diffstat (limited to 'coroutine.h')
-rw-r--r-- | coroutine.h | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/coroutine.h b/coroutine.h index d22eb2e..ae52f22 100644 --- a/coroutine.h +++ b/coroutine.h @@ -8,65 +8,60 @@ #define _COROUTINE_H_ #include <stddef.h> /* for size_t */ -#include <stdbool.h> /* for bool, true, false */ +#include <stdbool.h> /* for bool */ /* typedefs *******************************************************************/ + typedef size_t cid_t; /* 0=none; otherwise 1-indexed */ -typedef void (*cr_fn_t)(void *stack); -typedef struct { - cr_fn_t fn; - void *stack; - unsigned int state; - bool blocked; -} _cr_entry_t; +typedef void (*cr_fn_t)(void *args); -/* globals ********************************************************************/ -extern _cr_entry_t *_coroutine_table; -extern cid_t _cur_cid; +/* managing coroutines ********************************************************/ -/* bona-fide functions ********************************************************/ void coroutine_init(void); -cid_t coroutine_add(cr_fn_t fn, void *stack); -void coroutine_task(void); +cid_t coroutine_add(cr_fn_t fn, void *args); +void coroutine_main(void); + +/* inside of coroutines *******************************************************/ -/* core macros for use in a cr_fn_t() *****************************************/ -#define cr_begin() switch(_coroutine_table[_cur_cid].state) { case 0: -#define cr_exit() do { _coroutine_table[_cur_cid] = (cr_entry_t){0}; return; } while (0) -#define cr_yield() _cr_yield(__COUNTER__+1) -#define _cr_yield(_state) do { _coroutine_table[_cur_cid].state = _state; return; case _state:; } while (0) -#define cr_end() } +bool _cr_begin(void); +#define cr_begin() do { if (!_cr_begin()) return; } while (0) +void cr_exit(void); +void cr_yield(void); +void cr_pause_and_yield(void); +void cr_unpause(cid_t); +#define cr_end() + +cid_t cr_getcid(void); /* request/response channels **************************************************/ + #define cr_chan_t(req_t, resp_t) struct { \ cid_t requester; \ cid_t responder; \ req_t req; \ resp_t resp; \ } -#define cr_chan_req(ch, _resp_p, _req) do { \ - (ch)->requester = _cur_cid; \ - (ch)->req = (_req); \ - if ((ch)->responder != 0) \ - _coroutine_table[(ch)->responder].blocked = false; \ - _coroutine_table[_cur_cid].blocked = true; \ - cr_yield(); \ - if ((typeof(&(ch)->resp))(_resp_p)) \ - *((typeof(&(ch)->resp))(_resp_p)) = (ch)->resp; \ +#define cr_chan_req(ch, _resp_p, _req) do { \ + (ch)->requester = cr_getcid(); \ + (ch)->req = (_req); \ + if ((ch)->responder != 0) \ + cr_unpause((ch)->responder); \ + cr_pause_and_yield(); \ + if ((typeof(&(ch)->resp))(_resp_p)) \ + *((typeof(&(ch)->resp))(_resp_p)) = (ch)->resp; \ } while (0) #define cr_chan_have_req(ch) ((ch)->requester != 0) -#define cr_chan_recv_req(ch, _req_p) do { \ - (ch)->responder = _cur_cid; \ - if ((ch)->requester == 0) { \ - _coroutine_table[_cur_cid].blocked = true; \ - cr_yield(); \ - } \ - *(_req_p) = (ch)->req; \ +#define cr_chan_recv_req(ch, _req_p) do { \ + (ch)->responder = cr_getcid(); \ + if ((ch)->requester == 0) { \ + cr_pause_and_yield(); \ + *(_req_p) = (ch)->req; \ } while (0) -#define cr_chan_send_resp(ch, _resp) do { \ - (ch)->responder = 0; \ - (ch)->requester = 0; \ - (ch)->resp = (_resp); \ - _coroutine_table[(ch)->requester].blocked = false; \ +#define cr_chan_send_resp(ch, _resp) do { \ + cr_unpause((ch)->requester); \ + (ch)->responder = 0; \ + (ch)->requester = 0; \ + (ch)->resp = (_resp); \ } while (0) #endif /* _COROUTINE_H_ */ |