mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
sync/channels: expose ch.closed
as bool
pseudo attribute (#8244)
This commit is contained in:
parent
820e684313
commit
925ffd76f4
@ -2484,6 +2484,7 @@ res := ch.try_push(a) // try to perform `ch <- a`
|
||||
println(res)
|
||||
l := ch.len // number of elements in queue
|
||||
c := ch.cap // maximum queue length
|
||||
is_closed := ch.closed // bool flag - has `ch` been closed
|
||||
println(l)
|
||||
println(c)
|
||||
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
|
||||
the reason why not.
|
||||
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
|
||||
|
||||
|
@ -1,79 +1,73 @@
|
||||
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)
|
||||
for {
|
||||
mut a := 0
|
||||
if !ch.pop(&a) {
|
||||
a := <-ch or {
|
||||
break
|
||||
}
|
||||
sum += a
|
||||
}
|
||||
assert ch.closed == true
|
||||
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 {
|
||||
ch.push(&i)
|
||||
ch <- i
|
||||
}
|
||||
assert ch.closed == false
|
||||
ch.close()
|
||||
assert ch.closed == true
|
||||
}
|
||||
|
||||
fn test_channel_close_buffered_multi() {
|
||||
mut ch := sync.new_channel<int>(0)
|
||||
mut resch := sync.new_channel<i64>(100)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_send(mut ch)
|
||||
ch := chan int{cap: 10}
|
||||
resch := chan i64{}
|
||||
go do_rec(ch, resch)
|
||||
go do_rec(ch, resch)
|
||||
go do_rec(ch, resch)
|
||||
go do_rec(ch, resch)
|
||||
go do_send(ch)
|
||||
mut sum := i64(0)
|
||||
for _ in 0 .. 4 {
|
||||
mut r := i64(0)
|
||||
resch.pop(&r)
|
||||
sum += r
|
||||
sum += <- resch
|
||||
}
|
||||
assert sum == i64(8000) * (8000 - 1) / 2
|
||||
}
|
||||
|
||||
fn test_channel_close_unbuffered_multi() {
|
||||
mut ch := sync.new_channel<int>(0)
|
||||
mut resch := sync.new_channel<i64>(100)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_send(mut ch)
|
||||
ch := chan int{}
|
||||
resch := chan i64{}
|
||||
go do_rec(ch, resch)
|
||||
go do_rec(ch, resch)
|
||||
go do_rec(ch, resch)
|
||||
go do_rec(ch, resch)
|
||||
go do_send(ch)
|
||||
mut sum := i64(0)
|
||||
for _ in 0 .. 4 {
|
||||
mut r := i64(0)
|
||||
resch.pop(&r)
|
||||
sum += r
|
||||
sum += <-resch
|
||||
}
|
||||
assert sum == i64(8000) * (8000 - 1) / 2
|
||||
}
|
||||
|
||||
fn test_channel_close_buffered() {
|
||||
mut ch := sync.new_channel<int>(0)
|
||||
mut resch := sync.new_channel<i64>(100)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_send(mut ch)
|
||||
ch := chan int{cap: 100}
|
||||
resch := chan i64{}
|
||||
go do_rec(ch, resch)
|
||||
go do_send(ch)
|
||||
mut sum := i64(0)
|
||||
mut r := i64(0)
|
||||
resch.pop(&r)
|
||||
sum += r
|
||||
sum += <-resch
|
||||
assert sum == i64(8000) * (8000 - 1) / 2
|
||||
}
|
||||
|
||||
fn test_channel_close_unbuffered() {
|
||||
mut ch := sync.new_channel<int>(0)
|
||||
mut resch := sync.new_channel<i64>(100)
|
||||
go do_rec(mut ch, mut resch)
|
||||
go do_send(mut ch)
|
||||
ch := chan int{}
|
||||
resch := chan i64{cap: 100}
|
||||
go do_rec(ch, resch)
|
||||
go do_send(ch)
|
||||
mut sum := i64(0)
|
||||
mut r := i64(0)
|
||||
resch.pop(&r)
|
||||
sum += r
|
||||
sum += <-resch
|
||||
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))
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut ch Channel) closed() bool {
|
||||
return C.atomic_load_u16(&ch.closed) != 0
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut ch Channel) push(src voidptr) {
|
||||
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
|
||||
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 has_field := false
|
||||
|
@ -2933,8 +2933,8 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
g.write('$info.size')
|
||||
return
|
||||
}
|
||||
if sym.kind == .chan && node.field_name == 'len' {
|
||||
g.write('sync__Channel_len(')
|
||||
if sym.kind == .chan && (node.field_name == 'len' || node.field_name == 'closed') {
|
||||
g.write('sync__Channel_${node.field_name}(')
|
||||
g.expr(node.expr)
|
||||
g.write(')')
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user