summaryrefslogtreecommitdiff
path: root/libcr_ipc/include/libcr_ipc/_TODO_select.h
diff options
context:
space:
mode:
Diffstat (limited to 'libcr_ipc/include/libcr_ipc/_TODO_select.h')
-rw-r--r--libcr_ipc/include/libcr_ipc/_TODO_select.h65
1 files changed, 65 insertions, 0 deletions
diff --git a/libcr_ipc/include/libcr_ipc/_TODO_select.h b/libcr_ipc/include/libcr_ipc/_TODO_select.h
new file mode 100644
index 0000000..5510fc4
--- /dev/null
+++ b/libcr_ipc/include/libcr_ipc/_TODO_select.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-Licence-Identifier: AGPL-3.0-or-later
+ */
+
+struct _cr_select_arg {
+ enum _cr_select_op {
+ _CR_SELECT_NONE,
+ _CR_SELECT_RECV,
+ _CR_SELECT_SEND,
+ _CR_SELECT_DEFAULT,
+ } op;
+ struct _cr_chan *ch;
+ struct _cr_chan_waiter self;
+};
+#define CR_SELECT_RECV(ch) ((struct _cr_select_arg){.op=_CR_SELECT_RECV, sizeof((ch)->vals[0]), ch,
+#define CR_SELECT_SEND(ch) _CR_SELECT_SEND, sizeof((ch)->vals[0]), ch,
+#define CR_SELECT_DEFAULT _CR_SELECT_DEFAULT,
+#define CR_SELECT(OPS) switch(_cr_chan_select(OPS _CR_SELECT_NONE))
+
+size_t _cr_chan_select(enum _cr_select_op a, ...) {
+ restart:
+ size_t blocking, nonblocking;
+ bool have_default = false;
+
+ va_list args;
+ va_start(args, a);
+ bool first = true;
+ for (size_t i = 0; true; i++) {
+ enum _cr_select_op op;
+ if (first) {
+ op = a;
+ first = false;
+ } else
+ op = va_arg(args, enum _cr_select_op);
+ if (op == _CR_SELECT_NONE)
+ break;
+ else if (op == _CR_SELECT_DEFAULT) {
+ have_default = true;
+ continue;
+ }
+ size_t sz;
+ struct _cr_chan *ch;
+ sz = va_arg(args, size_t);
+ ch = va_arg(args, struct _cr_chan *);
+ if (op == _CR_SELECT_RECV) {
+ if (ch->waiters.front && ch->waiter_typ == _CH_CHAN_SENDER)
+ nonblocking++;
+ else
+ blocking++;
+ } else {
+ if (ch->waiters.front && ch->waiter_typ == _CH_CHAN_RECVER)
+ nonblocking++;
+ else
+ blocking++;
+ }
+ }
+ va_end(args);
+
+ random()
+
+ if (nonblocking == 0 && !have_default) {
+ goto restart;
+ }
+}