sync/channels: fixes for `try_push/pop()`, optimizations (#6352)

pull/6353/head
Uwe Krüger 2020-09-12 02:29:11 +02:00 committed by GitHub
parent 07b5d6b1b6
commit b10d79c4d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 8 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {