summaryrefslogtreecommitdiff
path: root/coroutine.h
diff options
context:
space:
mode:
Diffstat (limited to 'coroutine.h')
-rw-r--r--coroutine.h77
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_ */