소스 검색

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 <[email protected]>
Jack Mordaunt 3 달 전
부모
커밋
7f9589922d
1개의 변경된 파일22개의 추가작업 그리고 6개의 파일을 삭제
  1. 22 6
      core/sync/chan/chan.odin

+ 22 - 6
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
 }