1
0
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:
yuyi 2023-08-02 01:45:00 +08:00 committed by GitHub
parent b6d6d4b037
commit 600f891d3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 0 deletions

View File

@ -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))

View File

@ -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)

View File

@ -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
}

View File

@ -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 {

View 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]
}