cgen: implement channel `push()`/`pop()` using `<-` operator (#6154)

pull/6157/head
Uwe Krüger 2020-08-17 23:35:36 +02:00 committed by GitHub
parent 5c98c0760b
commit 0d7cc8829a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 21 deletions

View File

@ -1,45 +1,42 @@
import sync import sync
import time
fn do_rec_i64(ch chan i64) { fn do_rec_i64(ch chan i64) {
mut sum := i64(0) mut sum := i64(0)
for _ in 0 .. 300 { for _ in 0 .. 300 {
mut a := i64(0) sum += <-ch
(&sync.Channel(ch)).pop(&a)
sum += a
} }
assert sum == 300 * (300 - 1) / 2 assert sum == 300 * (300 - 1) / 2
} }
fn do_send_int(ch chan int) { fn do_send_int(ch chan int) {
for i in 0 .. 300 { for i in 0 .. 300 {
(&sync.Channel(ch)).push(&i) ch <- i
} }
} }
fn do_send_byte(ch chan byte) { fn do_send_byte(ch chan byte) {
for i in 0 .. 300 { for i in 0 .. 300 {
ii := byte(i) ch <- byte(i)
(&sync.Channel(ch)).push(&ii)
} }
} }
fn do_send_i64(mut ch sync.Channel) { fn do_send_i64(ch chan i64) {
for i in 0 .. 300 { for i in 0 .. 300 {
ii := i64(i) ch <- i
ch.push(&ii)
} }
} }
fn test_select() { fn test_select() {
chi := chan int{} chi := chan int{}
mut chl := sync.new_channel<i64>(1) chl := chan i64{cap: 1}
chb := chan byte{cap: 10} chb := chan byte{cap: 10}
recch := chan i64{cap: 0} recch := chan i64{cap: 0}
go do_rec_i64(recch) go do_rec_i64(recch)
go do_send_int(chi) go do_send_int(chi)
go do_send_byte(chb) go do_send_byte(chb)
go do_send_i64(mut chl) go do_send_i64(chl)
mut channels := [&sync.Channel(chi), &sync.Channel(recch), chl, &sync.Channel(chb)] mut channels := [&sync.Channel(chi), &sync.Channel(recch), &sync.Channel(chl), &sync.Channel(chb)]
directions := [sync.Direction.pop, .push, .pop, .pop] directions := [sync.Direction.pop, .push, .pop, .pop]
mut sum := i64(0) mut sum := i64(0)
mut rl := i64(0) mut rl := i64(0)
@ -73,4 +70,5 @@ fn test_select() {
256 * (256 - 1) / 2 + 256 * (256 - 1) / 2 +
44 * (44 - 1) / 2 44 * (44 - 1) / 2
assert sum == expected_sum assert sum == expected_sum
time.sleep_ms(20) // to give assert in coroutine enough time
} }

View File

@ -435,9 +435,11 @@ pub mut:
pub struct PrefixExpr { pub struct PrefixExpr {
pub: pub:
op token.Kind op token.Kind
right Expr right Expr
pos token.Position pos token.Position
pub mut:
right_type table.Type
} }
pub struct IndexExpr { pub struct IndexExpr {

View File

@ -2439,6 +2439,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
} }
ast.PrefixExpr { ast.PrefixExpr {
right_type := c.expr(node.right) right_type := c.expr(node.right)
node.right_type = right_type
// TODO: testing ref/deref strategy // TODO: testing ref/deref strategy
if node.op == .amp && !right_type.is_ptr() { if node.op == .amp && !right_type.is_ptr() {
return right_type.to_ptr() return right_type.to_ptr()

View File

@ -498,8 +498,21 @@ typedef struct {
g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};') g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
} }
.chan { .chan {
styp := util.no_dots(typ.name) if typ.name != 'chan' {
g.type_definitions.writeln('typedef chan $styp;') styp := util.no_dots(typ.name)
g.type_definitions.writeln('typedef chan $styp;')
el_stype := g.typ(typ.chan_info().elem_type)
g.hotcode_definitions.writeln('
static inline $el_stype __${styp}_popval($styp ch) {
$el_stype val;
sync__Channel_try_pop_priv(ch, &val, false);
return val;
}')
g.hotcode_definitions.writeln('
static inline void __${styp}_pushval($styp ch, $el_stype val) {
sync__Channel_try_push_priv(ch, &val, false);
}')
}
} }
.map { .map {
styp := util.no_dots(typ.name) styp := util.no_dots(typ.name)
@ -1969,11 +1982,20 @@ fn (mut g Gen) expr(node ast.Expr) {
if node.op == .amp { if node.op == .amp {
g.is_amp = true g.is_amp = true
} }
// g.write('/*pref*/') if node.op == .arrow {
g.write(node.op.str()) right_type := g.unwrap_generic(node.right_type)
// g.write('(') right_sym := g.table.get_type_symbol(right_type)
styp := util.no_dots(right_sym.name)
g.write('__${styp}_popval(')
} else {
// g.write('/*pref*/')
g.write(node.op.str())
// g.write('(')
}
g.expr(node.right) g.expr(node.right)
// g.write(')') if node.op == .arrow {
g.write(')')
}
g.is_amp = false g.is_amp = false
} }
ast.RangeExpr { ast.RangeExpr {
@ -2326,6 +2348,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
} }
g.write(' }))') g.write(' }))')
} }
} else if node.op == .arrow {
// chan <- val
styp := util.no_dots(left_sym.name)
g.write('__${styp}_pushval(')
g.expr(node.left)
g.write(', ')
g.expr(node.right)
g.write(')')
} else if unaliased_left.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_right.is_signed() && } else if unaliased_left.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_right.is_signed() &&
node.op in [.eq, .ne, .gt, .lt, .ge, .le] { node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
bitsize := if unaliased_left.idx() == table.u32_type_idx && bitsize := if unaliased_left.idx() == table.u32_type_idx &&