mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
core/sync/chan: (unbuffered) ack reads
This fixes an issue where a call to close could intercept the dance between send and recv, causing send to report incorrectly that a value was not transmitted (when it actually was).
This commit is contained in:
@@ -83,6 +83,8 @@ Raw_Chan :: struct {
|
||||
r_waiting: int, // guarded by `mutex`
|
||||
w_waiting: int, // guarded by `mutex`
|
||||
|
||||
did_read: bool, // lets a sender know if the value was read
|
||||
|
||||
// Buffered
|
||||
queue: ^Raw_Queue,
|
||||
|
||||
@@ -628,14 +630,20 @@ send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
c.did_read = false
|
||||
defer c.did_read = false
|
||||
|
||||
mem.copy(c.unbuffered_data, msg_in, int(c.msg_size))
|
||||
|
||||
c.w_waiting += 1
|
||||
|
||||
if c.r_waiting > 0 {
|
||||
sync.signal(&c.r_cond)
|
||||
}
|
||||
|
||||
sync.wait(&c.w_cond, &c.mutex)
|
||||
|
||||
if c.closed {
|
||||
if c.closed && !c.did_read {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -713,8 +721,7 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) {
|
||||
} else if c.unbuffered_data != nil { // unbuffered
|
||||
sync.guard(&c.mutex)
|
||||
|
||||
for !c.closed &&
|
||||
c.w_waiting == 0 {
|
||||
for !c.closed && c.w_waiting == 0 {
|
||||
c.r_waiting += 1
|
||||
sync.wait(&c.r_cond, &c.mutex)
|
||||
c.r_waiting -= 1
|
||||
@@ -727,6 +734,7 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) {
|
||||
mem.copy(msg_out, c.unbuffered_data, int(c.msg_size))
|
||||
c.w_waiting -= 1
|
||||
|
||||
c.did_read = true
|
||||
sync.signal(&c.w_cond)
|
||||
ok = true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user