sync/channels: expose `ch.closed` as `bool` pseudo attribute (#8244)
parent
820e684313
commit
925ffd76f4
|
@ -2484,6 +2484,7 @@ res := ch.try_push(a) // try to perform `ch <- a`
|
||||||
println(res)
|
println(res)
|
||||||
l := ch.len // number of elements in queue
|
l := ch.len // number of elements in queue
|
||||||
c := ch.cap // maximum queue length
|
c := ch.cap // maximum queue length
|
||||||
|
is_closed := ch.closed // bool flag - has `ch` been closed
|
||||||
println(l)
|
println(l)
|
||||||
println(c)
|
println(c)
|
||||||
mut b := Abc{}
|
mut b := Abc{}
|
||||||
|
@ -2495,7 +2496,10 @@ The `try_push/pop()` methods will return immediately with one of the results
|
||||||
`.success`, `.not_ready` or `.closed` - dependent on whether the object has been transferred or
|
`.success`, `.not_ready` or `.closed` - dependent on whether the object has been transferred or
|
||||||
the reason why not.
|
the reason why not.
|
||||||
Usage of these methods and properties in production is not recommended -
|
Usage of these methods and properties in production is not recommended -
|
||||||
algorithms based on them are often subject to race conditions. Use `select` instead.
|
algorithms based on them are often subject to race conditions. Especially `.len` and
|
||||||
|
`.closed` should not be used to make decisions.
|
||||||
|
Use `or` branches, error propagation or `select` instead (see [Syntax and Usage](#syntax-and-usage)
|
||||||
|
and [Channel Select](#channel-select) above).
|
||||||
|
|
||||||
### Shared Objects
|
### Shared Objects
|
||||||
|
|
||||||
|
|
|
@ -1,79 +1,73 @@
|
||||||
import sync
|
import sync
|
||||||
|
|
||||||
fn do_rec(mut ch sync.Channel, mut resch sync.Channel) {
|
fn do_rec(ch chan int, resch chan i64) {
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
for {
|
for {
|
||||||
mut a := 0
|
a := <-ch or {
|
||||||
if !ch.pop(&a) {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sum += a
|
sum += a
|
||||||
}
|
}
|
||||||
|
assert ch.closed == true
|
||||||
println(sum)
|
println(sum)
|
||||||
resch.push(&sum)
|
resch <- sum
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_send(mut ch sync.Channel) {
|
fn do_send(ch chan int) {
|
||||||
for i in 0 .. 8000 {
|
for i in 0 .. 8000 {
|
||||||
ch.push(&i)
|
ch <- i
|
||||||
}
|
}
|
||||||
|
assert ch.closed == false
|
||||||
ch.close()
|
ch.close()
|
||||||
|
assert ch.closed == true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_channel_close_buffered_multi() {
|
fn test_channel_close_buffered_multi() {
|
||||||
mut ch := sync.new_channel<int>(0)
|
ch := chan int{cap: 10}
|
||||||
mut resch := sync.new_channel<i64>(100)
|
resch := chan i64{}
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_send(mut ch)
|
go do_send(ch)
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
for _ in 0 .. 4 {
|
for _ in 0 .. 4 {
|
||||||
mut r := i64(0)
|
sum += <- resch
|
||||||
resch.pop(&r)
|
|
||||||
sum += r
|
|
||||||
}
|
}
|
||||||
assert sum == i64(8000) * (8000 - 1) / 2
|
assert sum == i64(8000) * (8000 - 1) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_channel_close_unbuffered_multi() {
|
fn test_channel_close_unbuffered_multi() {
|
||||||
mut ch := sync.new_channel<int>(0)
|
ch := chan int{}
|
||||||
mut resch := sync.new_channel<i64>(100)
|
resch := chan i64{}
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_send(mut ch)
|
go do_send(ch)
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
for _ in 0 .. 4 {
|
for _ in 0 .. 4 {
|
||||||
mut r := i64(0)
|
sum += <-resch
|
||||||
resch.pop(&r)
|
|
||||||
sum += r
|
|
||||||
}
|
}
|
||||||
assert sum == i64(8000) * (8000 - 1) / 2
|
assert sum == i64(8000) * (8000 - 1) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_channel_close_buffered() {
|
fn test_channel_close_buffered() {
|
||||||
mut ch := sync.new_channel<int>(0)
|
ch := chan int{cap: 100}
|
||||||
mut resch := sync.new_channel<i64>(100)
|
resch := chan i64{}
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_send(mut ch)
|
go do_send(ch)
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
mut r := i64(0)
|
sum += <-resch
|
||||||
resch.pop(&r)
|
|
||||||
sum += r
|
|
||||||
assert sum == i64(8000) * (8000 - 1) / 2
|
assert sum == i64(8000) * (8000 - 1) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_channel_close_unbuffered() {
|
fn test_channel_close_unbuffered() {
|
||||||
mut ch := sync.new_channel<int>(0)
|
ch := chan int{}
|
||||||
mut resch := sync.new_channel<i64>(100)
|
resch := chan i64{cap: 100}
|
||||||
go do_rec(mut ch, mut resch)
|
go do_rec(ch, resch)
|
||||||
go do_send(mut ch)
|
go do_send(ch)
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
mut r := i64(0)
|
sum += <-resch
|
||||||
resch.pop(&r)
|
|
||||||
sum += r
|
|
||||||
assert sum == i64(8000) * (8000 - 1) / 2
|
assert sum == i64(8000) * (8000 - 1) / 2
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,11 @@ pub fn (mut ch Channel) len() int {
|
||||||
return int(C.atomic_load_u32(&ch.read_avail))
|
return int(C.atomic_load_u32(&ch.read_avail))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (mut ch Channel) closed() bool {
|
||||||
|
return C.atomic_load_u16(&ch.closed) != 0
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut ch Channel) push(src voidptr) {
|
pub fn (mut ch Channel) push(src voidptr) {
|
||||||
if ch.try_push_priv(src, false) == .closed {
|
if ch.try_push_priv(src, false) == .closed {
|
||||||
|
|
|
@ -2080,6 +2080,10 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
|
||||||
selector_expr.typ = table.int_type
|
selector_expr.typ = table.int_type
|
||||||
return table.int_type
|
return table.int_type
|
||||||
}
|
}
|
||||||
|
if sym.kind == .chan && field_name == 'closed' {
|
||||||
|
selector_expr.typ = table.bool_type
|
||||||
|
return table.bool_type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mut unknown_field_msg := 'type `$sym.name` has no field or method `$field_name`'
|
mut unknown_field_msg := 'type `$sym.name` has no field or method `$field_name`'
|
||||||
mut has_field := false
|
mut has_field := false
|
||||||
|
|
|
@ -2933,8 +2933,8 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||||
g.write('$info.size')
|
g.write('$info.size')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sym.kind == .chan && node.field_name == 'len' {
|
if sym.kind == .chan && (node.field_name == 'len' || node.field_name == 'closed') {
|
||||||
g.write('sync__Channel_len(')
|
g.write('sync__Channel_${node.field_name}(')
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue