mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker, cgen: implement fixed array of threads wait() (#19032)
This commit is contained in:
parent
b6d6d4b037
commit
600f891d3a
@ -1654,6 +1654,26 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
node.return_type = left_sym.info.return_type
|
node.return_type = left_sym.info.return_type
|
||||||
return left_sym.info.return_type
|
return left_sym.info.return_type
|
||||||
|
} else if final_left_sym.info is ast.ArrayFixed && method_name == 'wait' {
|
||||||
|
elem_sym := c.table.sym(final_left_sym.info.elem_type)
|
||||||
|
if elem_sym.kind == .thread {
|
||||||
|
if node.args.len != 0 {
|
||||||
|
c.error('`.wait()` does not have any arguments', node.args[0].pos)
|
||||||
|
}
|
||||||
|
thread_ret_type := c.unwrap_generic(elem_sym.thread_info().return_type)
|
||||||
|
if thread_ret_type.has_flag(.option) {
|
||||||
|
c.error('`.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.',
|
||||||
|
node.pos)
|
||||||
|
} else if thread_ret_type.has_flag(.result) {
|
||||||
|
c.error('`.wait()` cannot be called for an array when thread functions return results. Iterate over the arrays elements instead and handle each returned result with `or`.',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
node.return_type = c.table.find_or_register_array(thread_ret_type)
|
||||||
|
return node.return_type
|
||||||
|
} else {
|
||||||
|
c.error('`${left_sym.name}` has no method `wait()` (only thread handles and arrays of them have)',
|
||||||
|
node.left.pos())
|
||||||
|
}
|
||||||
} else if left_sym.kind == .char && left_type.nr_muls() == 0 && method_name == 'str' {
|
} else if left_sym.kind == .char && left_type.nr_muls() == 0 && method_name == 'str' {
|
||||||
c.error('calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead',
|
c.error('calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead',
|
||||||
node.left.pos().extend(node.pos))
|
node.left.pos().extend(node.pos))
|
||||||
|
@ -1067,6 +1067,18 @@ fn (mut g Gen) gen_array_wait(node ast.CallExpr) {
|
|||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_fixed_array_wait(node ast.CallExpr) {
|
||||||
|
arr := g.table.sym(g.unwrap_generic(node.receiver_type))
|
||||||
|
thread_type := arr.array_fixed_info().elem_type
|
||||||
|
thread_sym := g.table.sym(thread_type)
|
||||||
|
thread_ret_type := thread_sym.thread_info().return_type
|
||||||
|
eltyp := g.table.sym(thread_ret_type).cname
|
||||||
|
fn_name := g.register_thread_fixed_array_wait_call(node, eltyp)
|
||||||
|
g.write('${fn_name}(')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_array_any(node ast.CallExpr) {
|
fn (mut g Gen) gen_array_any(node ast.CallExpr) {
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
mut s := g.go_before_stmt(0)
|
mut s := g.go_before_stmt(0)
|
||||||
|
@ -1287,6 +1287,52 @@ ${ret_typ} ${fn_name}(${thread_arr_typ} a) {
|
|||||||
return fn_name
|
return fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) register_thread_fixed_array_wait_call(node ast.CallExpr, eltyp string) string {
|
||||||
|
is_void := eltyp == 'void'
|
||||||
|
thread_typ := if is_void { '__v_thread' } else { '__v_thread_${eltyp}' }
|
||||||
|
ret_typ := if is_void { 'void' } else { 'Array_${eltyp}' }
|
||||||
|
rec_sym := g.table.sym(node.receiver_type)
|
||||||
|
len := (rec_sym.info as ast.ArrayFixed).size
|
||||||
|
thread_arr_typ := rec_sym.cname
|
||||||
|
fn_name := '${thread_arr_typ}_wait'
|
||||||
|
mut should_register := false
|
||||||
|
lock g.waiter_fns {
|
||||||
|
if fn_name !in g.waiter_fns {
|
||||||
|
g.waiter_fns << fn_name
|
||||||
|
should_register = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if should_register {
|
||||||
|
if is_void {
|
||||||
|
g.register_thread_void_wait_call()
|
||||||
|
g.gowrappers.writeln('
|
||||||
|
void ${fn_name}(${thread_arr_typ} a) {
|
||||||
|
for (int i = 0; i < ${len}; ++i) {
|
||||||
|
${thread_typ} t = ((${thread_typ}*)a)[i];
|
||||||
|
if (t == 0) continue;
|
||||||
|
__v_thread_wait(t);
|
||||||
|
}
|
||||||
|
}')
|
||||||
|
} else {
|
||||||
|
g.gowrappers.writeln('
|
||||||
|
${ret_typ} ${fn_name}(${thread_arr_typ} a) {
|
||||||
|
${ret_typ} res = __new_array_with_default(${len}, ${len}, sizeof(${eltyp}), 0);
|
||||||
|
for (int i = 0; i < ${len}; ++i) {
|
||||||
|
${thread_typ} t = ((${thread_typ}*)a)[i];')
|
||||||
|
if g.pref.os == .windows {
|
||||||
|
g.gowrappers.writeln('\t\tif (t.handle == 0) continue;')
|
||||||
|
} else {
|
||||||
|
g.gowrappers.writeln('\t\tif (t == 0) continue;')
|
||||||
|
}
|
||||||
|
g.gowrappers.writeln('\t\t((${eltyp}*)res.data)[i] = __v_thread_${eltyp}_wait(t);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fn_name
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) register_chan_pop_option_call(opt_el_type string, styp string) {
|
fn (mut g Gen) register_chan_pop_option_call(opt_el_type string, styp string) {
|
||||||
g.chan_pop_options[opt_el_type] = styp
|
g.chan_pop_options[opt_el_type] = styp
|
||||||
}
|
}
|
||||||
|
@ -1250,6 +1250,9 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||||||
if g.gen_array_method_call(node, left_type) {
|
if g.gen_array_method_call(node, left_type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if left_sym.kind == .array_fixed && node.name == 'wait' {
|
||||||
|
g.gen_fixed_array_wait(node)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if final_left_sym.kind == .map {
|
if final_left_sym.kind == .map {
|
||||||
|
15
vlib/v/tests/fixed_array_of_threads_wait_test.v
Normal file
15
vlib/v/tests/fixed_array_of_threads_wait_test.v
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
fn foo() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_fixed_array_of_threads_wait() {
|
||||||
|
threads := [
|
||||||
|
spawn foo(),
|
||||||
|
spawn foo(),
|
||||||
|
]!
|
||||||
|
|
||||||
|
results := threads.wait()
|
||||||
|
|
||||||
|
println(results)
|
||||||
|
assert results == [true, true]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user