cgen: fix parallel waiter function generation (#12895)

pull/12898/head
Leo Developer 2021-12-19 12:38:48 +01:00 committed by GitHub
parent 2ab861ef89
commit a7019ac86c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 32 additions and 17 deletions

View File

@ -132,7 +132,7 @@ mut:
str_types []StrType // types that need automatic str() generation str_types []StrType // types that need automatic str() generation
generated_str_fns []StrType // types that already have a str() function generated_str_fns []StrType // types that already have a str() function
threaded_fns shared []string // for generating unique wrapper types and fns for `go xxx()` threaded_fns shared []string // for generating unique wrapper types and fns for `go xxx()`
waiter_fns []string // functions that wait for `go xxx()` to finish waiter_fns shared []string // functions that wait for `go xxx()` to finish
needed_equality_fns []ast.Type needed_equality_fns []ast.Type
generated_eq_fns []ast.Type generated_eq_fns []ast.Type
array_sort_fn shared []string array_sort_fn shared []string
@ -328,7 +328,6 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
global_g.nr_closures += g.nr_closures global_g.nr_closures += g.nr_closures
global_g.has_main = global_g.has_main || g.has_main global_g.has_main = global_g.has_main || g.has_main
global_g.waiter_fns << g.waiter_fns
global_g.auto_fn_definitions << g.auto_fn_definitions global_g.auto_fn_definitions << g.auto_fn_definitions
global_g.anon_fn_definitions << g.anon_fn_definitions global_g.anon_fn_definitions << g.anon_fn_definitions
global_g.needed_equality_fns << g.needed_equality_fns // duplicates are resolved later in gen_equality_fns global_g.needed_equality_fns << g.needed_equality_fns // duplicates are resolved later in gen_equality_fns
@ -525,6 +524,7 @@ fn cgen_process_one_file_cb(p &pool.PoolProcessor, idx int, wid int) &Gen {
inner_loop: &ast.EmptyStmt{} inner_loop: &ast.EmptyStmt{}
field_data_type: ast.Type(global_g.table.find_type_idx('FieldData')) field_data_type: ast.Type(global_g.table.find_type_idx('FieldData'))
array_sort_fn: global_g.array_sort_fn array_sort_fn: global_g.array_sort_fn
waiter_fns: global_g.waiter_fns
threaded_fns: global_g.threaded_fns threaded_fns: global_g.threaded_fns
done_optionals: global_g.done_optionals done_optionals: global_g.done_optionals
is_autofree: global_g.pref.autofree is_autofree: global_g.pref.autofree
@ -961,20 +961,23 @@ fn (mut g Gen) write_shareds() {
} }
fn (mut g Gen) register_thread_void_wait_call() { fn (mut g Gen) register_thread_void_wait_call() {
if '__v_thread_wait' !in g.waiter_fns { lock g.waiter_fns {
g.gowrappers.writeln('void __v_thread_wait(__v_thread thread) {') if '__v_thread_wait' in g.waiter_fns {
if g.pref.os == .windows { return
g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread, INFINITE);')
} else {
g.gowrappers.writeln('\tint stat = pthread_join(thread, (void **)NULL);')
} }
g.gowrappers.writeln('\tif (stat != 0) { _v_panic(_SLIT("unable to join thread")); }')
if g.pref.os == .windows {
g.gowrappers.writeln('\tCloseHandle(thread);')
}
g.gowrappers.writeln('}')
g.waiter_fns << '__v_thread_wait' g.waiter_fns << '__v_thread_wait'
} }
g.gowrappers.writeln('void __v_thread_wait(__v_thread thread) {')
if g.pref.os == .windows {
g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread, INFINITE);')
} else {
g.gowrappers.writeln('\tint stat = pthread_join(thread, (void **)NULL);')
}
g.gowrappers.writeln('\tif (stat != 0) { _v_panic(_SLIT("unable to join thread")); }')
if g.pref.os == .windows {
g.gowrappers.writeln('\tCloseHandle(thread);')
}
g.gowrappers.writeln('}')
} }
fn (mut g Gen) register_thread_array_wait_call(eltyp string) string { fn (mut g Gen) register_thread_array_wait_call(eltyp string) string {
@ -983,8 +986,14 @@ fn (mut g Gen) register_thread_array_wait_call(eltyp string) string {
ret_typ := if is_void { 'void' } else { 'Array_$eltyp' } ret_typ := if is_void { 'void' } else { 'Array_$eltyp' }
thread_arr_typ := 'Array_$thread_typ' thread_arr_typ := 'Array_$thread_typ'
fn_name := '${thread_arr_typ}_wait' fn_name := '${thread_arr_typ}_wait'
if fn_name !in g.waiter_fns { mut should_register := false
g.waiter_fns << fn_name 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 { if is_void {
g.register_thread_void_wait_call() g.register_thread_void_wait_call()
g.gowrappers.writeln(' g.gowrappers.writeln('
@ -6991,7 +7000,14 @@ fn (mut g Gen) go_expr(node ast.GoExpr) {
handle = 'thread_$tmp' handle = 'thread_$tmp'
// create wait handler for this return type if none exists // create wait handler for this return type if none exists
waiter_fn_name := gohandle_name + '_wait' waiter_fn_name := gohandle_name + '_wait'
if waiter_fn_name !in g.waiter_fns { mut should_register := false
lock g.waiter_fns {
if waiter_fn_name !in g.waiter_fns {
g.waiter_fns << waiter_fn_name
should_register = true
}
}
if should_register {
g.gowrappers.writeln('\n$s_ret_typ ${waiter_fn_name}($gohandle_name thread) {') g.gowrappers.writeln('\n$s_ret_typ ${waiter_fn_name}($gohandle_name thread) {')
mut c_ret_ptr_ptr := 'NULL' mut c_ret_ptr_ptr := 'NULL'
if node.call_expr.return_type != ast.void_type { if node.call_expr.return_type != ast.void_type {
@ -7022,7 +7038,6 @@ fn (mut g Gen) go_expr(node ast.GoExpr) {
g.gowrappers.writeln('\treturn ret;') g.gowrappers.writeln('\treturn ret;')
} }
g.gowrappers.writeln('}') g.gowrappers.writeln('}')
g.waiter_fns << waiter_fn_name
} }
} }
// Register the wrapper type and function // Register the wrapper type and function