all: extend `wait()` method to array of `thread` handles (#8840)
parent
ac1c4932e7
commit
5306b2788c
|
@ -96,6 +96,7 @@ const (
|
||||||
'vlib/v/tests/generic_chan_test.v',
|
'vlib/v/tests/generic_chan_test.v',
|
||||||
'vlib/v/tests/generics_method_test.v',
|
'vlib/v/tests/generics_method_test.v',
|
||||||
'vlib/v/tests/generics_test.v',
|
'vlib/v/tests/generics_test.v',
|
||||||
|
'vlib/v/tests/go_array_wait_test.v',
|
||||||
'vlib/v/tests/go_call_generic_fn_test.v',
|
'vlib/v/tests/go_call_generic_fn_test.v',
|
||||||
'vlib/v/tests/go_wait_2_test.v',
|
'vlib/v/tests/go_wait_2_test.v',
|
||||||
'vlib/v/tests/interface_edge_cases/assign_to_interface_field_test.v',
|
'vlib/v/tests/interface_edge_cases/assign_to_interface_field_test.v',
|
||||||
|
|
|
@ -29,7 +29,7 @@ const (
|
||||||
valid_comp_if_platforms = ['amd64', 'aarch64', 'x64', 'x32', 'little_endian', 'big_endian']
|
valid_comp_if_platforms = ['amd64', 'aarch64', 'x64', 'x32', 'little_endian', 'big_endian']
|
||||||
valid_comp_if_other = ['js', 'debug', 'test', 'glibc', 'prealloc', 'no_bounds_checking']
|
valid_comp_if_other = ['js', 'debug', 'test', 'glibc', 'prealloc', 'no_bounds_checking']
|
||||||
array_builtin_methods = ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort',
|
array_builtin_methods = ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort',
|
||||||
'contains', 'index']
|
'contains', 'index', 'wait']
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct Checker {
|
pub struct Checker {
|
||||||
|
@ -1306,10 +1306,11 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
is_filter_map := method_name in ['filter', 'map']
|
is_filter_map := method_name in ['filter', 'map']
|
||||||
is_sort := method_name == 'sort'
|
is_sort := method_name == 'sort'
|
||||||
is_slice := method_name == 'slice'
|
is_slice := method_name == 'slice'
|
||||||
|
is_wait := method_name == 'wait'
|
||||||
if is_slice && !c.is_builtin_mod {
|
if is_slice && !c.is_builtin_mod {
|
||||||
c.error('.slice() is a private method, use `x[start..end]` instead', call_expr.pos)
|
c.error('.slice() is a private method, use `x[start..end]` instead', call_expr.pos)
|
||||||
}
|
}
|
||||||
if is_filter_map || is_sort {
|
if is_filter_map || is_sort || is_wait {
|
||||||
array_info := left_type_sym.info as table.Array
|
array_info := left_type_sym.info as table.Array
|
||||||
if is_filter_map {
|
if is_filter_map {
|
||||||
// position of `it` doesn't matter
|
// position of `it` doesn't matter
|
||||||
|
@ -1328,6 +1329,19 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elem_typ = array_info.elem_type
|
elem_typ = array_info.elem_type
|
||||||
|
if is_wait {
|
||||||
|
elem_sym := c.table.get_type_symbol(elem_typ)
|
||||||
|
if elem_sym.kind == .thread {
|
||||||
|
if call_expr.args.len != 0 {
|
||||||
|
c.error('wait() does not have any arguments', call_expr.args[0].pos)
|
||||||
|
}
|
||||||
|
thread_ret_type := elem_sym.thread_info().return_type
|
||||||
|
call_expr.return_type = c.table.find_or_register_array(thread_ret_type)
|
||||||
|
} else {
|
||||||
|
c.error('`$left_type_sym.name` has no method `wait()` (only thread handles and arrays of them have)',
|
||||||
|
call_expr.left.position())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// map/filter are supposed to have 1 arg only
|
// map/filter are supposed to have 1 arg only
|
||||||
mut arg_type := left_type
|
mut arg_type := left_type
|
||||||
|
@ -1409,8 +1423,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
if !c.check_types(arg_type, info.elem_type) && !c.check_types(left_type, arg_type) {
|
if !c.check_types(arg_type, info.elem_type) && !c.check_types(left_type, arg_type) {
|
||||||
c.error('cannot $method_name `$arg_sym.name` to `$left_type_sym.name`', arg_expr.position())
|
c.error('cannot $method_name `$arg_sym.name` to `$left_type_sym.name`', arg_expr.position())
|
||||||
}
|
}
|
||||||
} else if left_type_sym.kind == .gohandle && method_name == 'wait' {
|
} else if left_type_sym.kind == .thread && method_name == 'wait' {
|
||||||
info := left_type_sym.info as table.GoHandle
|
info := left_type_sym.info as table.Thread
|
||||||
if call_expr.args.len > 0 {
|
if call_expr.args.len > 0 {
|
||||||
c.error('wait() does not have any arguments', call_expr.args[0].pos)
|
c.error('wait() does not have any arguments', call_expr.args[0].pos)
|
||||||
}
|
}
|
||||||
|
@ -3611,7 +3625,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
}
|
}
|
||||||
ast.GoExpr {
|
ast.GoExpr {
|
||||||
ret_type := c.call_expr(mut node.go_stmt.call_expr)
|
ret_type := c.call_expr(mut node.go_stmt.call_expr)
|
||||||
return c.table.find_or_register_gohandle(ret_type)
|
return c.table.find_or_register_thread(ret_type)
|
||||||
}
|
}
|
||||||
ast.ChanInit {
|
ast.ChanInit {
|
||||||
return c.chan_init(mut node)
|
return c.chan_init(mut node)
|
||||||
|
|
|
@ -556,3 +556,16 @@ fn (mut g Gen) gen_array_index(node ast.CallExpr) {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(node.args[0].expr)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_array_wait(node ast.CallExpr) {
|
||||||
|
arr := g.table.get_type_symbol(node.receiver_type)
|
||||||
|
thread_type := arr.array_info().elem_type
|
||||||
|
thread_sym := g.table.get_type_symbol(thread_type)
|
||||||
|
thread_ret_type := thread_sym.thread_info().return_type
|
||||||
|
eltyp := g.table.get_type_symbol(thread_ret_type).cname
|
||||||
|
fn_name := g.register_thread_array_wait_call(eltyp)
|
||||||
|
g.write('${fn_name}(')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -619,6 +619,36 @@ fn (mut g Gen) find_or_register_shared(t table.Type, base string) string {
|
||||||
return sh_typ
|
return sh_typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) register_thread_array_wait_call(eltyp string) string {
|
||||||
|
thread_typ := '__v_thread_$eltyp'
|
||||||
|
ret_typ := if eltyp == '' { 'void' } else { 'Array_$eltyp' }
|
||||||
|
thread_arr_typ := 'Array_$thread_typ'
|
||||||
|
fn_name := '${thread_arr_typ}_wait'
|
||||||
|
if fn_name !in g.waiter_fns {
|
||||||
|
g.waiter_fns << fn_name
|
||||||
|
if eltyp == 'void' {
|
||||||
|
g.gowrappers.writeln('
|
||||||
|
void ${fn_name}($thread_arr_typ a) {
|
||||||
|
for (int i = 0; i < a.len; ++i) {
|
||||||
|
$thread_typ t = (($thread_typ*)a.data)[i];
|
||||||
|
__v_thread_${eltyp}_wait(t);
|
||||||
|
}
|
||||||
|
}')
|
||||||
|
} else {
|
||||||
|
g.gowrappers.writeln('
|
||||||
|
$ret_typ ${fn_name}($thread_arr_typ a) {
|
||||||
|
$ret_typ res = __new_array_with_default(a.len, a.len, sizeof($eltyp), 0);
|
||||||
|
for (int i = 0; i < a.len; ++i) {
|
||||||
|
$thread_typ t = (($thread_typ*)a.data)[i];
|
||||||
|
(($eltyp*)res.data)[i] = __v_thread_${eltyp}_wait(t);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fn_name
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) register_chan_pop_optional_call(opt_el_type string, styp string) {
|
fn (mut g Gen) register_chan_pop_optional_call(opt_el_type string, styp string) {
|
||||||
if opt_el_type !in g.chan_pop_optionals {
|
if opt_el_type !in g.chan_pop_optionals {
|
||||||
g.chan_pop_optionals << opt_el_type
|
g.chan_pop_optionals << opt_el_type
|
||||||
|
@ -3097,20 +3127,34 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
} else if op_is_eq_or_ne && left_sym.kind == .array && right_sym.kind == .array {
|
} else if op_is_eq_or_ne && left_sym.kind == .array && right_sym.kind == .array {
|
||||||
ptr_typ := g.gen_array_equality_fn(left_type)
|
ptr_typ := g.gen_array_equality_fn(left_type.clear_flag(.shared_f))
|
||||||
if node.op == .ne {
|
if node.op == .ne {
|
||||||
g.write('!')
|
g.write('!')
|
||||||
}
|
}
|
||||||
g.write('${ptr_typ}_arr_eq(')
|
g.write('${ptr_typ}_arr_eq(')
|
||||||
if node.left_type.is_ptr() {
|
if node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
|
if node.left_type.has_flag(.shared_f) {
|
||||||
|
if node.left_type.is_ptr() {
|
||||||
|
g.write('->val')
|
||||||
|
} else {
|
||||||
|
g.write('.val')
|
||||||
|
}
|
||||||
|
}
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
if node.right_type.is_ptr() {
|
if node.right_type.is_ptr() && !node.right_type.has_flag(.shared_f) {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
|
if node.right_type.has_flag(.shared_f) {
|
||||||
|
if node.right_type.is_ptr() {
|
||||||
|
g.write('->val')
|
||||||
|
} else {
|
||||||
|
g.write('.val')
|
||||||
|
}
|
||||||
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if op_is_eq_or_ne && left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
|
} else if op_is_eq_or_ne && left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
|
||||||
ptr_typ := g.gen_fixed_array_equality_fn(left_type)
|
ptr_typ := g.gen_fixed_array_equality_fn(left_type)
|
||||||
|
@ -5330,9 +5374,9 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
||||||
table.Alias {
|
table.Alias {
|
||||||
// table.Alias { TODO
|
// table.Alias { TODO
|
||||||
}
|
}
|
||||||
table.GoHandle {
|
table.Thread {
|
||||||
if g.pref.os == .windows {
|
if g.pref.os == .windows {
|
||||||
if name == 'gohandle_void' {
|
if name == '__v_thread_void' {
|
||||||
g.type_definitions.writeln('typedef HANDLE $name;')
|
g.type_definitions.writeln('typedef HANDLE $name;')
|
||||||
} else {
|
} else {
|
||||||
// Windows can only return `u32` (no void*) from a thread, so the
|
// Windows can only return `u32` (no void*) from a thread, so the
|
||||||
|
@ -5825,7 +5869,7 @@ fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
||||||
if g.pref.os == .windows && node.call_expr.return_type != table.void_type {
|
if g.pref.os == .windows && node.call_expr.return_type != table.void_type {
|
||||||
g.writeln('$arg_tmp_var->ret_ptr = malloc(sizeof($s_ret_typ));')
|
g.writeln('$arg_tmp_var->ret_ptr = malloc(sizeof($s_ret_typ));')
|
||||||
}
|
}
|
||||||
gohandle_name := 'gohandle_' +
|
gohandle_name := '__v_thread_' +
|
||||||
g.table.get_type_symbol(g.unwrap_generic(node.call_expr.return_type)).cname
|
g.table.get_type_symbol(g.unwrap_generic(node.call_expr.return_type)).cname
|
||||||
if g.pref.os == .windows {
|
if g.pref.os == .windows {
|
||||||
simple_handle := if joinable && node.call_expr.return_type != table.void_type {
|
simple_handle := if joinable && node.call_expr.return_type != table.void_type {
|
||||||
|
|
|
@ -532,6 +532,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.gen_array_index(node)
|
g.gen_array_index(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
'wait' {
|
||||||
|
g.gen_array_wait(node)
|
||||||
|
return
|
||||||
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,8 +165,8 @@ pub fn (mut g JsGen) typ(t table.Type) string {
|
||||||
.aggregate {
|
.aggregate {
|
||||||
panic('TODO: unhandled aggregate in JS')
|
panic('TODO: unhandled aggregate in JS')
|
||||||
}
|
}
|
||||||
.gohandle {
|
.thread {
|
||||||
panic('TODO: unhandled gohandle in JS')
|
panic('TODO: unhandled thread in JS')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -102,16 +102,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
comments << p.eat_comments({})
|
comments << p.eat_comments({})
|
||||||
mut right_comments := []ast.Comment{}
|
mut right_comments := []ast.Comment{}
|
||||||
mut right := []ast.Expr{cap: left.len}
|
mut right := []ast.Expr{cap: left.len}
|
||||||
if p.tok.kind == .key_go {
|
|
||||||
stmt := p.stmt(false)
|
|
||||||
go_stmt := stmt as ast.GoStmt
|
|
||||||
right << ast.GoExpr{
|
|
||||||
go_stmt: go_stmt
|
|
||||||
pos: go_stmt.pos
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
right, right_comments = p.expr_list()
|
right, right_comments = p.expr_list()
|
||||||
}
|
|
||||||
comments << right_comments
|
comments << right_comments
|
||||||
end_comments := p.eat_comments(same_line: true)
|
end_comments := p.eat_comments(same_line: true)
|
||||||
mut has_cross_var := false
|
mut has_cross_var := false
|
||||||
|
|
|
@ -106,7 +106,8 @@ pub fn (mut p Parser) parse_map_type() table.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) parse_chan_type() table.Type {
|
pub fn (mut p Parser) parse_chan_type() table.Type {
|
||||||
if p.peek_tok.kind != .name && p.peek_tok.kind != .key_mut && p.peek_tok.kind != .amp {
|
if p.peek_tok.kind != .name && p.peek_tok.kind != .key_mut && p.peek_tok.kind != .amp
|
||||||
|
&& p.peek_tok.kind != .lsbr {
|
||||||
p.next()
|
p.next()
|
||||||
return table.chan_type
|
return table.chan_type
|
||||||
}
|
}
|
||||||
|
@ -118,6 +119,18 @@ pub fn (mut p Parser) parse_chan_type() table.Type {
|
||||||
return table.new_type(idx)
|
return table.new_type(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut p Parser) parse_thread_type() table.Type {
|
||||||
|
if p.peek_tok.kind != .name && p.peek_tok.kind != .key_mut && p.peek_tok.kind != .amp
|
||||||
|
&& p.peek_tok.kind != .lsbr {
|
||||||
|
p.next()
|
||||||
|
return table.thread_type
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
elem_type := p.parse_type()
|
||||||
|
idx := p.table.find_or_register_thread(elem_type)
|
||||||
|
return table.new_type(idx)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) parse_multi_return_type() table.Type {
|
pub fn (mut p Parser) parse_multi_return_type() table.Type {
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
mut mr_types := []table.Type{}
|
mut mr_types := []table.Type{}
|
||||||
|
@ -319,6 +332,9 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool, check
|
||||||
if name == 'chan' {
|
if name == 'chan' {
|
||||||
return p.parse_chan_type()
|
return p.parse_chan_type()
|
||||||
}
|
}
|
||||||
|
if name == 'thread' {
|
||||||
|
return p.parse_thread_type()
|
||||||
|
}
|
||||||
defer {
|
defer {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,14 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
node = p.prefix_expr()
|
node = p.prefix_expr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.key_go {
|
||||||
|
stmt := p.stmt(false)
|
||||||
|
go_stmt := stmt as ast.GoStmt
|
||||||
|
node = ast.GoExpr{
|
||||||
|
go_stmt: go_stmt
|
||||||
|
pos: go_stmt.pos
|
||||||
|
}
|
||||||
|
}
|
||||||
.key_true, .key_false {
|
.key_true, .key_false {
|
||||||
node = ast.BoolLiteral{
|
node = ast.BoolLiteral{
|
||||||
val: p.tok.kind == .key_true
|
val: p.tok.kind == .key_true
|
||||||
|
|
|
@ -484,17 +484,17 @@ pub fn (t &Table) chan_cname(elem_type Type, is_mut bool) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) gohandle_name(return_type Type) string {
|
pub fn (t &Table) thread_name(return_type Type) string {
|
||||||
return_type_sym := t.get_type_symbol(return_type)
|
return_type_sym := t.get_type_symbol(return_type)
|
||||||
ptr := if return_type.is_ptr() { '&' } else { '' }
|
ptr := if return_type.is_ptr() { '&' } else { '' }
|
||||||
return 'gohandle[$ptr$return_type_sym.name]'
|
return 'thread $ptr$return_type_sym.name'
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) gohandle_cname(return_type Type) string {
|
pub fn (t &Table) thread_cname(return_type Type) string {
|
||||||
return_type_sym := t.get_type_symbol(return_type)
|
return_type_sym := t.get_type_symbol(return_type)
|
||||||
suffix := if return_type.is_ptr() { '_ptr' } else { '' }
|
suffix := if return_type.is_ptr() { '_ptr' } else { '' }
|
||||||
return 'gohandle_$return_type_sym.cname$suffix'
|
return '__v_thread_$return_type_sym.cname$suffix'
|
||||||
}
|
}
|
||||||
|
|
||||||
// map_source_name generates the original name for the v source.
|
// map_source_name generates the original name for the v source.
|
||||||
|
@ -560,25 +560,25 @@ pub fn (mut t Table) find_or_register_map(key_type Type, value_type Type) int {
|
||||||
return t.register_type_symbol(map_typ)
|
return t.register_type_symbol(map_typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut t Table) find_or_register_gohandle(return_type Type) int {
|
pub fn (mut t Table) find_or_register_thread(return_type Type) int {
|
||||||
name := t.gohandle_name(return_type)
|
name := t.thread_name(return_type)
|
||||||
cname := t.gohandle_cname(return_type)
|
cname := t.thread_cname(return_type)
|
||||||
// existing
|
// existing
|
||||||
existing_idx := t.type_idxs[name]
|
existing_idx := t.type_idxs[name]
|
||||||
if existing_idx > 0 {
|
if existing_idx > 0 {
|
||||||
return existing_idx
|
return existing_idx
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
gohandle_typ := TypeSymbol{
|
thread_typ := TypeSymbol{
|
||||||
parent_idx: gohandle_type_idx
|
parent_idx: thread_type_idx
|
||||||
kind: .gohandle
|
kind: .thread
|
||||||
name: name
|
name: name
|
||||||
cname: cname
|
cname: cname
|
||||||
info: GoHandle{
|
info: Thread{
|
||||||
return_type: return_type
|
return_type: return_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t.register_type_symbol(gohandle_typ)
|
return t.register_type_symbol(thread_typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut t Table) find_or_register_array(elem_type Type) int {
|
pub fn (mut t Table) find_or_register_array(elem_type Type) int {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import strings
|
||||||
pub type Type = int
|
pub type Type = int
|
||||||
|
|
||||||
pub type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType | GenericStructInst |
|
pub type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType | GenericStructInst |
|
||||||
GoHandle | Interface | Map | MultiReturn | Struct | SumType
|
Interface | Map | MultiReturn | Struct | SumType | Thread
|
||||||
|
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
v
|
v
|
||||||
|
@ -306,7 +306,7 @@ pub const (
|
||||||
any_type_idx = 25
|
any_type_idx = 25
|
||||||
float_literal_type_idx = 26
|
float_literal_type_idx = 26
|
||||||
int_literal_type_idx = 27
|
int_literal_type_idx = 27
|
||||||
gohandle_type_idx = 28
|
thread_type_idx = 28
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
|
@ -350,14 +350,14 @@ pub const (
|
||||||
any_type = new_type(any_type_idx)
|
any_type = new_type(any_type_idx)
|
||||||
float_literal_type = new_type(float_literal_type_idx)
|
float_literal_type = new_type(float_literal_type_idx)
|
||||||
int_literal_type = new_type(int_literal_type_idx)
|
int_literal_type = new_type(int_literal_type_idx)
|
||||||
gohandle_type = new_type(gohandle_type_idx)
|
thread_type = new_type(thread_type_idx)
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16',
|
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16',
|
||||||
'u32', 'u64', 'int_literal', 'f32', 'f64', 'float_literal', 'string', 'ustring', 'char',
|
'u32', 'u64', 'int_literal', 'f32', 'f64', 'float_literal', 'string', 'ustring', 'char',
|
||||||
'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'chan', 'any', 'struct', 'mapnode',
|
'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'chan', 'any', 'struct', 'mapnode',
|
||||||
'size_t', 'rune', 'gohandle']
|
'size_t', 'rune', 'thread']
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct MultiReturn {
|
pub struct MultiReturn {
|
||||||
|
@ -419,7 +419,7 @@ pub enum Kind {
|
||||||
float_literal
|
float_literal
|
||||||
int_literal
|
int_literal
|
||||||
aggregate
|
aggregate
|
||||||
gohandle
|
thread
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &TypeSymbol) str() string {
|
pub fn (t &TypeSymbol) str() string {
|
||||||
|
@ -471,10 +471,10 @@ pub fn (t &TypeSymbol) chan_info() Chan {
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &TypeSymbol) gohandle_info() GoHandle {
|
pub fn (t &TypeSymbol) thread_info() Thread {
|
||||||
match mut t.info {
|
match mut t.info {
|
||||||
GoHandle { return t.info }
|
Thread { return t.info }
|
||||||
else { panic('TypeSymbol.gohandle_info(): no gohandle info for type: $t.name') }
|
else { panic('TypeSymbol.thread_info(): no thread info for type: $t.name') }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +540,7 @@ pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
cname: 'int_literal'
|
cname: 'int_literal'
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
)
|
)
|
||||||
t.register_type_symbol(kind: .gohandle, name: 'gohandle', cname: 'gohandle', mod: 'builtin')
|
t.register_type_symbol(kind: .thread, name: 'thread', cname: '__v_thread', mod: 'builtin')
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -619,7 +619,7 @@ pub fn (k Kind) str() string {
|
||||||
.generic_struct_inst { 'generic_struct_inst' }
|
.generic_struct_inst { 'generic_struct_inst' }
|
||||||
.rune { 'rune' }
|
.rune { 'rune' }
|
||||||
.aggregate { 'aggregate' }
|
.aggregate { 'aggregate' }
|
||||||
.gohandle { 'gohandle' }
|
.thread { 'thread' }
|
||||||
}
|
}
|
||||||
return k_str
|
return k_str
|
||||||
}
|
}
|
||||||
|
@ -730,7 +730,7 @@ pub mut:
|
||||||
is_mut bool
|
is_mut bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GoHandle {
|
pub struct Thread {
|
||||||
pub mut:
|
pub mut:
|
||||||
return_type Type
|
return_type Type
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
fn f(x f64) f64 {
|
||||||
|
y := x * x
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_array_thread_f64_wait() {
|
||||||
|
mut r := []thread f64{cap: 10}
|
||||||
|
for i in 0 .. 10 {
|
||||||
|
r << go f(f64(i) + 0.5)
|
||||||
|
}
|
||||||
|
x := r.wait()
|
||||||
|
assert x == [0.25, 2.25, 6.25, 12.25, 20.25, 30.25, 42.25, 56.25, 72.25, 90.25]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g(shared a []int, i int) {
|
||||||
|
lock a {
|
||||||
|
a[i] *= a[i] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_array_thread_void_wait() {
|
||||||
|
shared a := [2 3 5 7 11 13 17]
|
||||||
|
t := [
|
||||||
|
go g(shared a, 0)
|
||||||
|
go g(shared a, 3)
|
||||||
|
go g(shared a, 6)
|
||||||
|
go g(shared a, 2)
|
||||||
|
go g(shared a, 1)
|
||||||
|
go g(shared a, 5)
|
||||||
|
go g(shared a, 4)
|
||||||
|
]
|
||||||
|
println('threads started')
|
||||||
|
t.wait()
|
||||||
|
rlock a {
|
||||||
|
assert a == [6, 12, 30, 56, 132, 182, 306]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue