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
|
||||
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' {
|
||||
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))
|
||||
|
@ -1067,6 +1067,18 @@ fn (mut g Gen) gen_array_wait(node ast.CallExpr) {
|
||||
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) {
|
||||
tmp := g.new_tmp_var()
|
||||
mut s := g.go_before_stmt(0)
|
||||
|
@ -1287,6 +1287,52 @@ ${ret_typ} ${fn_name}(${thread_arr_typ} a) {
|
||||
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) {
|
||||
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) {
|
||||
return
|
||||
}
|
||||
} else if left_sym.kind == .array_fixed && node.name == 'wait' {
|
||||
g.gen_fixed_array_wait(node)
|
||||
return
|
||||
}
|
||||
|
||||
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