Skip to content

Commit

Permalink
cgen: implement channel push()/pop() using <- operator (#6154)
Browse files Browse the repository at this point in the history
  • Loading branch information
UweKrueger committed Aug 17, 2020
1 parent 5c98c07 commit 0d7cc88
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 21 deletions.
22 changes: 10 additions & 12 deletions vlib/sync/channel_select_2_test.v
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
import sync
import time

fn do_rec_i64(ch chan i64) {
mut sum := i64(0)
for _ in 0 .. 300 {
mut a := i64(0)
(&sync.Channel(ch)).pop(&a)
sum += a
sum += <-ch
}
assert sum == 300 * (300 - 1) / 2
}

fn do_send_int(ch chan int) {
for i in 0 .. 300 {
(&sync.Channel(ch)).push(&i)
ch <- i
}
}

fn do_send_byte(ch chan byte) {
for i in 0 .. 300 {
ii := byte(i)
(&sync.Channel(ch)).push(&ii)
ch <- byte(i)
}
}

fn do_send_i64(mut ch sync.Channel) {
fn do_send_i64(ch chan i64) {
for i in 0 .. 300 {
ii := i64(i)
ch.push(&ii)
ch <- i
}
}

fn test_select() {
chi := chan int{}
mut chl := sync.new_channel<i64>(1)
chl := chan i64{cap: 1}
chb := chan byte{cap: 10}
recch := chan i64{cap: 0}
go do_rec_i64(recch)
go do_send_int(chi)
go do_send_byte(chb)
go do_send_i64(mut chl)
mut channels := [&sync.Channel(chi), &sync.Channel(recch), chl, &sync.Channel(chb)]
go do_send_i64(chl)
mut channels := [&sync.Channel(chi), &sync.Channel(recch), &sync.Channel(chl), &sync.Channel(chb)]
directions := [sync.Direction.pop, .push, .pop, .pop]
mut sum := i64(0)
mut rl := i64(0)
Expand Down Expand Up @@ -73,4 +70,5 @@ fn test_select() {
256 * (256 - 1) / 2 +
44 * (44 - 1) / 2
assert sum == expected_sum
time.sleep_ms(20) // to give assert in coroutine enough time
}
8 changes: 5 additions & 3 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,11 @@ pub mut:

pub struct PrefixExpr {
pub:
op token.Kind
right Expr
pos token.Position
op token.Kind
right Expr
pos token.Position
pub mut:
right_type table.Type
}

pub struct IndexExpr {
Expand Down
1 change: 1 addition & 0 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -2439,6 +2439,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
}
ast.PrefixExpr {
right_type := c.expr(node.right)
node.right_type = right_type
// TODO: testing ref/deref strategy
if node.op == .amp && !right_type.is_ptr() {
return right_type.to_ptr()
Expand Down
42 changes: 36 additions & 6 deletions vlib/v/gen/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,21 @@ typedef struct {
g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
}
.chan {
styp := util.no_dots(typ.name)
g.type_definitions.writeln('typedef chan $styp;')
if typ.name != 'chan' {
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 {
styp := util.no_dots(typ.name)
Expand Down Expand Up @@ -1969,11 +1982,20 @@ fn (mut g Gen) expr(node ast.Expr) {
if node.op == .amp {
g.is_amp = true
}
// g.write('/*pref*/')
g.write(node.op.str())
// g.write('(')
if node.op == .arrow {
right_type := g.unwrap_generic(node.right_type)
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.write(')')
if node.op == .arrow {
g.write(')')
}
g.is_amp = false
}
ast.RangeExpr {
Expand Down Expand Up @@ -2326,6 +2348,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
}
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() &&
node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
bitsize := if unaliased_left.idx() == table.u32_type_idx &&
Expand Down

0 comments on commit 0d7cc88

Please sign in to comment.