aboutsummaryrefslogtreecommitdiff
path: root/core/sync
diff options
context:
space:
mode:
authorJack Mordaunt <jackmordaunt.dev@gmail.com>2025-06-05 15:27:24 -0300
committerJack Mordaunt <jackmordaunt.dev@gmail.com>2025-06-12 16:14:51 -0300
commit7f9589922db4f2006287c1e3fc11e5ab308b9de3 (patch)
tree76485dd90874b379781a92cdf63c4b44fbb8a061 /core/sync
parent0ed6cdc98eead010b448a10ac2c45d2695563be9 (diff)
core/sync.select_raw: return a useful index
This fixes a flaw in the original implementation: the returned index is actually useless to the caller. This is because the index returned refers to the internal "candidate" list. This list is dynamic, and may not have all of the input channels (if they weren't ready according to chan.can_{recv,send}). That means the index is not guaranteed to mean anything to the caller. The fix introduced here is to return the index into the input slice (recvs,sends) and an enum to specify which input slice that is. If no selection was made, then (-1, .None) is returned to communicate as much. Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Diffstat (limited to 'core/sync')
-rw-r--r--core/sync/chan/chan.odin28
1 files changed, 22 insertions, 6 deletions
diff --git a/core/sync/chan/chan.odin b/core/sync/chan/chan.odin
index eca4c28d7..610cf16eb 100644
--- a/core/sync/chan/chan.odin
+++ b/core/sync/chan/chan.odin
@@ -1105,6 +1105,15 @@ can_send :: proc "contextless" (c: ^Raw_Chan) -> bool {
return c.w_waiting == 0
}
+/*
+Specifies the direction of the selected channel.
+*/
+Select_Status :: enum {
+ None,
+ Recv,
+ Send,
+}
+
/*
Attempts to either send or receive messages on the specified channels.
@@ -1170,7 +1179,7 @@ Output:
*/
@(require_results)
-select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []rawptr, recv_out: rawptr) -> (select_idx: int, ok: bool) #no_bounds_check {
+select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []rawptr, recv_out: rawptr) -> (select_idx: int, status: Select_Status) #no_bounds_check {
Select_Op :: struct {
idx: int, // local to the slice that was given
is_recv: bool,
@@ -1204,15 +1213,22 @@ select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []
return
}
- select_idx = rand.int_max(count) if count > 0 else 0
+ candidate_idx := rand.int_max(count) if count > 0 else 0
- sel := candidates[select_idx]
+ sel := candidates[candidate_idx]
if sel.is_recv {
- ok = recv_raw(recvs[sel.idx], recv_out)
+ status = .Recv
+ if !recv_raw(recvs[sel.idx], recv_out) {
+ return -1, .None
+ }
} else {
- ok = send_raw(sends[sel.idx], send_msgs[sel.idx])
+ status = .Send
+ if !send_raw(sends[sel.idx], send_msgs[sel.idx]) {
+ return -1, .None
+ }
}
- return
+
+ return sel.idx, status
}