diff --git a/vlib/sync/bench/results.md b/vlib/sync/bench/results.md index 4b32bd50e5..e791a0cac6 100644 --- a/vlib/sync/bench/results.md +++ b/vlib/sync/bench/results.md @@ -20,10 +20,10 @@ nobj .... number of objects to pass thru the channel | nsend | nrec | buflen | **V (gcc -O2)** | **V (clang)** | **V (tcc)** | **Go (glang)** | **Go (gccgo -O2)** | | :---: | :---:| :---: | :---: | :---: | :---: | :---: | :---: | -| 1 | 1 | 0 | 0.95 | 0.72 | 0.66 | 4.65 | 0.56 | -| 1 | 1 | 100 | 3.26 | 2.51 | 2.24 | 18.90 | 6.08 | -| 4 | 4 | 0 | 0.25 | 0.26 | 0.24 | 1.84 | 0.84 | -| 4 | 4 | 100 | 3.11 | 2.78 | 2.63 | 7.43 | 3.71 | +| 1 | 1 | 0 | 1.97 | 1.63 | 2.08 | 4.65 | 0.56 | +| 1 | 1 | 100 | 3.05 | 2.29 | 1.93 | 18.90 | 6.08 | +| 4 | 4 | 0 | 0.87 | 0.90 | 0.99 | 1.84 | 0.84 | +| 4 | 4 | 100 | 3.35 | 3.07 | 2.92 | 7.43 | 3.71 | ## AMD Ryzen 7 3800X, Windows 10 2004 x64 diff --git a/vlib/sync/channel_try_buf_test.v b/vlib/sync/channel_try_buf_test.v new file mode 100755 index 0000000000..6a0a88dfa3 --- /dev/null +++ b/vlib/sync/channel_try_buf_test.v @@ -0,0 +1,17 @@ +fn test_channel_try_buffered() { + ch := chan int{cap: 5} + for z in 2..13 { + if ch.try_push(z) == .not_ready { + assert z == 7 + break + } + } + mut obj := int(0) + for ch.try_pop(obj) == .success { + println(obj) + } + assert obj == 6 + ch <- 17 + obj = <-ch + assert obj == 17 +} diff --git a/vlib/sync/channel_try_unbuf_test.v b/vlib/sync/channel_try_unbuf_test.v new file mode 100644 index 0000000000..45dbe33443 --- /dev/null +++ b/vlib/sync/channel_try_unbuf_test.v @@ -0,0 +1,13 @@ +fn test_channel_try_unbuffered() { + ch := chan int{} + for z in 5..8 { + if ch.try_push(z) == .not_ready { + assert z == 5 + break + } + panic('push on non-ready channel not detected') + } + mut obj := -17 + for ch.try_pop(obj) == .success {} + assert obj == -17 +} diff --git a/vlib/sync/channels.v b/vlib/sync/channels.v index 0bcfaecbbc..0c212f8329 100644 --- a/vlib/sync/channels.v +++ b/vlib/sync/channels.v @@ -165,14 +165,14 @@ pub fn (mut ch Channel) push(src voidptr) { [inline] pub fn (mut ch Channel) try_push(src voidptr) ChanState { - return ch.try_push_priv(src, false) + return ch.try_push_priv(src, true) } fn (mut ch Channel) try_push_priv(src voidptr, no_block bool) ChanState { if C.atomic_load_u16(&ch.closed) != 0 { return .closed } - spinloops_sem_, spinloops_ := if no_block { spinloops, spinloops_sem } else { 1, 1 } + spinloops_sem_, spinloops_ := if no_block { 1, 1 } else { spinloops, spinloops_sem } mut have_swapped := false for { mut got_sem := false @@ -200,6 +200,9 @@ fn (mut ch Channel) try_push_priv(src voidptr, no_block bool) ChanState { got_sem = ch.writesem.try_wait() } if !got_sem { + if no_block { + return .not_ready + } ch.writesem.wait() } if ch.cap == 0 { @@ -311,6 +314,9 @@ fn (mut ch Channel) try_push_priv(src voidptr, no_block bool) ChanState { } return .success } else { + if no_block { + return .not_ready + } ch.writesem.post() } } @@ -324,11 +330,11 @@ pub fn (mut ch Channel) pop(dest voidptr) bool { [inline] pub fn (mut ch Channel) try_pop(dest voidptr) ChanState { - return ch.try_pop_priv(dest, false) + return ch.try_pop_priv(dest, true) } fn (mut ch Channel) try_pop_priv(dest voidptr, no_block bool) ChanState { - spinloops_sem_, spinloops_ := if no_block { spinloops, spinloops_sem } else { 1, 1 } + spinloops_sem_, spinloops_ := if no_block { 1, 1 } else { spinloops, spinloops_sem } mut have_swapped := false mut write_in_progress := false for {