blob: ae52f2208efbb93005ccf176d025f00935c02f6c (
plain)
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
|
/* coroutine.h - Simple coroutine and request/response implementation
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-Licence-Identifier: AGPL-3.0-or-later
*/
#ifndef _COROUTINE_H_
#define _COROUTINE_H_
#include <stddef.h> /* for size_t */
#include <stdbool.h> /* for bool */
/* typedefs *******************************************************************/
typedef size_t cid_t; /* 0=none; otherwise 1-indexed */
typedef void (*cr_fn_t)(void *args);
/* managing coroutines ********************************************************/
void coroutine_init(void);
cid_t coroutine_add(cr_fn_t fn, void *args);
void coroutine_main(void);
/* inside of coroutines *******************************************************/
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 = 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 = cr_getcid(); \
if ((ch)->requester == 0) { \
cr_pause_and_yield(); \
*(_req_p) = (ch)->req; \
} while (0)
#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_ */
|