cgen, coroutines: fix go expr handle referencing undeclared thread__tN (#27379)
This commit is contained in:
1 parent
44c55f6649
commit
3d22ea2334
3 files changed
+51
-2
No files matched your search
@@ -0,0 +1,24 @@
|
||||
// vtest build: false // This should be built with: `v -use-coroutines go_handle.v`
|
||||
// Note: the Photon wrapper is not yet trivial enough to build/install on the CI.
|
||||
//
|
||||
// Demonstrates storing the handle returned by a `go` expression and waiting on
|
||||
// it. Because the Photon coroutine wrapper exposes no joinable handle, a `go`
|
||||
// whose handle is used is lowered to the regular `spawn` (pthread) path, so the
|
||||
// handle can be waited on just like `spawn`.
|
||||
module main
|
||||
|
||||
struct App {
|
||||
mut:
|
||||
worker thread
|
||||
}
|
||||
|
||||
fn (a App) loop() {
|
||||
println('hello from the worker coroutine')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut a := App{}
|
||||
a.worker = go a.loop()
|
||||
a.worker.wait()
|
||||
println('done')
|
||||
}
|
||||
@@ -15,8 +15,19 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
|
||||
if node.call_expr.should_be_skipped {
|
||||
return
|
||||
}
|
||||
is_spawn := mode == .spawn_
|
||||
is_go := mode == .go_
|
||||
mut is_spawn := mode == .spawn_
|
||||
mut is_go := mode == .go_
|
||||
if is_go && node.is_expr {
|
||||
// A `go expr` whose handle is used as a value (e.g. `h := go f()` or
|
||||
// `obj.field = go f()`) needs a real, joinable thread handle. The photon
|
||||
// coroutine wrapper (`photon_thread_create*`) returns void and exposes no
|
||||
// such handle, so fall back to the regular `spawn` (pthread) path here,
|
||||
// which declares and assigns the `thread_<tmp>` handle that is read back
|
||||
// as the expression's value. Plain statement form `go f()` (no handle
|
||||
// used) keeps using the photon work-pool path below.
|
||||
is_spawn = true
|
||||
is_go = false
|
||||
}
|
||||
if is_spawn {
|
||||
g.writeln('/*spawn (thread) */')
|
||||
} else {
|
||||
|
||||
@@ -1079,6 +1079,20 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
ast.GoExpr {
|
||||
if node.is_expr {
|
||||
w.fn_by_name('free')
|
||||
// A `go expr` whose handle is used as a value is lowered to the
|
||||
// `spawn` (pthread) codegen path (see spawn_and_go_expr), since the
|
||||
// photon coroutine wrapper returns no joinable handle. Mark the same
|
||||
// thread-handle type and pthread error helpers that `spawn` needs,
|
||||
// otherwise -skip-unused prunes them and the generated C fails to link.
|
||||
w.mark_by_type(w.table.find_or_register_thread(node.call_expr.return_type))
|
||||
w.uses_spawn = true
|
||||
if w.pref.os == .windows {
|
||||
w.fn_by_name('panic_lasterr')
|
||||
w.fn_by_name('winapi_lasterr_str')
|
||||
} else {
|
||||
w.fn_by_name('c_error_number_str')
|
||||
w.fn_by_name('panic_error_number')
|
||||
}
|
||||
}
|
||||
w.mark_by_type(node.call_expr.return_type)
|
||||
w.expr(node.call_expr)
|
||||
|
||||
Reference in new issue
Block a user