diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-24 14:32:52 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-24 14:32:52 -0600 |
commit | e980a44cea166e765e0dee98e8202a54cde1b142 (patch) | |
tree | 130cc3c4fb11b6ee9f300f8636303434e51017cc | |
parent | a4f85408baae4ed6e1df24d3d342da55fbbd3e0c (diff) |
coroutine_rpc.h: tidy, do less copying
-rw-r--r-- | coroutine_rpc.h | 55 |
1 files changed, 31 insertions, 24 deletions
diff --git a/coroutine_rpc.h b/coroutine_rpc.h index 00aa165..b51445e 100644 --- a/coroutine_rpc.h +++ b/coroutine_rpc.h @@ -17,15 +17,19 @@ * cr_rpc_t(req_t, resp_t) returns the type definition for a * rcp-channel on which the requester submits a value of type `req_t` * and the responder responds with a value of type `resp_t`. + * + * There must only ever be 1 concurrent writer and 1 concurrent + * reader. If you need 1:n, n:1, or m:n; then you should instead use a + * series of coroutine_chan.h. */ -#define cr_rpc_t(req_t, resp_t) struct { \ - cid_t requester; \ - cid_t responder; \ - req_t req; \ - resp_t resp; \ +#define cr_rpc_t(req_t, resp_t) struct { \ + cid_t requester; \ + cid_t responder; \ + req_t *req_p; \ + resp_t *resp_p; \ } -/* These are "functions" are preprocessor macros instead of real C +/* These "functions" are preprocessor macros instead of real C * functions so that the compiler can do type-checking instead of * having these functions take `void*`. */ @@ -33,17 +37,16 @@ * ch_rpc_req(cr_rpc_t(req_t, resp_t) *ch, resp_t *resp, req_t req) * submits the `req` request to `ch` puts the response in `*resp_p`. * - * Blocks until the responder has called both cr_rpc_recv_req() and - * cr_rpc_send_resp(). + * Blocking: Always; until the responder has called both + * cr_rpc_recv_req() and cr_rpc_send_resp(). */ -#define cr_rpc_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; \ +#define cr_rpc_req(ch, _resp_p, _req) do { \ + (ch)->requester = cr_getcid(); \ + (ch)->req_p = &(_req); \ + (ch)->resp_p = (_resp_p; \ + if ((ch)->responder != 0) \ + cr_unpause((ch)->responder); \ + cr_pause_and_yield(); \ } while (0) /** @@ -51,7 +54,7 @@ * to check whether or not there is a request waiting to be received * (with cr_rpc_recv_req()) without blocking if there is not. * - * Never blocks. + * Blocking: Never. */ #define cr_rpc_have_req(ch) ((ch)->requester != 0) @@ -60,25 +63,29 @@ * a request from ch into `*req_p`. * * If there is not a pending request on `ch`, blocks until there is. + * + * Blocking: Maybe. */ #define cr_rpc_recv_req(ch, _req_p) do { \ (ch)->responder = cr_getcid(); \ if ((ch)->requester == 0) \ cr_pause_and_yield(); \ - *(_req_p) = (ch)->req; \ + *(_req_p) = *((ch)->req_p); \ + (ch)->req_p = NULL; \ } while (0) /** * cr_rpc_send_resp(cr_rpc_t(req_t, resp_t) *ch, resp_t resp) sends * the reply to the most-recently-read request. * - * Never blocks. + * Blocking: Never. */ -#define cr_rpc_send_resp(ch, _resp) do { \ - cr_unpause((ch)->requester); \ - (ch)->responder = 0; \ - (ch)->requester = 0; \ - (ch)->resp = (_resp); \ +#define cr_rpc_send_resp(ch, _resp) do { \ + cr_unpause((ch)->requester); \ + (ch)->responder = 0; \ + (ch)->requester = 0; \ + *((ch)->resp_p) = (_resp); \ + (ch)->resp_p = NULL; \ } while (0) #endif /* _COROUTINE_RPC_H_ */ |