Documentation
¶
Overview ¶
Package mainthread offers facilities to schedule functions on the main thread. To use this package properly, one must call `mainthread.Init` from the main package. For example:
package main
import "golang.design/x/runtime/mainthread"
func main() { mainthread.Init(fn) }
// fn is the actual main function
func fn() {
// ... do stuff ...
// mainthread.Call returns when f1 returns. Note that if f1 blocks
// it will also block the execution of any subsequent calls on the
// main thread.
mainthread.Call(f1)
// ... do stuff ...
// mainthread.Go returns immediately and f2 is scheduled to be
// executed in the future.
mainthread.Go(f2)
// mainthread.CallV is the value-returning counterpart of Call.
v := mainthread.CallV(f3)
// ... do stuff ...
}
func f1() { ... }
func f2() { ... }
func f3() int { ... }
If the given function triggers a panic, and called via `mainthread.Call`, then the original panic value is propagated to the calling goroutine, preserving its type. One can capture that panic, when possible:
defer func() {
if r := recover(); r != nil {
println(r)
}
}()
mainthread.Call(func() { ... }) // if panic
If the given function triggers a panic, and called via `mainthread.Go`, then the panic will be cached internally, until a call to the `Error()` method:
mainthread.Go(func() { ... }) // if panics
// ... do stuff ...
if err := mainthread.Error(); err != nil { // can be captured here.
println(err)
}
Note that a panic happens before `mainthread.Error()` returning the panicked error. If one needs to guarantee `mainthread.Error()` indeed captured the panic, a dummy function can be used as synchornization:
mainthread.Go(func() { panic("die") }) // if panics
mainthread.Call(func() {}) // for execution synchronization
err := mainthread.Error() // err must be non-nil
It is possible to cache up to a maximum of 42 panicked errors. More errors are ignored.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Call ¶
func Call(f func())
Call calls f on the main thread and blocks until f finishes.
If f panics, the original panic value is re-panicked on the calling goroutine, preserving its type.
Example ¶
package main
import (
"fmt"
"golang.design/x/runtime/mainthread"
)
func main() {
mainthread.Init(func() {
mainthread.Call(func() {
fmt.Println("from main thread")
})
})
}
Output: from main thread
func CallV ¶
func CallV[T any](f func() T) (v T)
CallV calls f on the main thread, blocks until f finishes, and returns the value produced by f. It is the value-returning counterpart of Call.
Unlike Call, CallV allocates: f is wrapped in a closure that captures the return value, so it is not suitable for allocation-sensitive hot paths. If f panics, the original panic value is re-panicked on the calling goroutine, preserving its type.
Example ¶
package main
import (
"fmt"
"golang.design/x/runtime/mainthread"
)
func main() {
mainthread.Init(func() {
n := mainthread.CallV(func() int {
return 42
})
fmt.Println(n)
})
}
Output: 42
func Error ¶
func Error() error
Error returns an error that is captured if there are any panics happened on the mainthread.
It is possible to cache up to a maximum of 42 panicked errors. More errors are ignored.
func Go ¶
func Go(f func())
Go schedules f to be called on the main thread.
Example ¶
package main
import (
"fmt"
"golang.design/x/runtime/mainthread"
)
func main() {
mainthread.Init(func() {
done := make(chan string)
mainthread.Go(func() {
done <- "main thread"
})
fmt.Println("from", <-done)
})
}
Output: from main thread
func Init ¶
func Init(main func())
Init initializes the functionality of running arbitrary subsequent functions be called on the main system thread.
Init must be called in the main.main function.
Example ¶
package main
import (
"golang.design/x/runtime/mainthread"
)
func main() {
mainthread.Init(func() {
// ... Do stuff ...
})
}
Output:
Types ¶
This section is empty.