sync/channels: fixes for `try_push/pop()`, optimizations (#6352)
parent
07b5d6b1b6
commit
b10d79c4d9
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue