// Package osthread allows functions to be called on the main operating system thread. // // Usage: // // func main() { // osthread.Start(Entrypoint) // Initialize osthread and calls Entrypoint. Blocks until Entrypoint returns. // } // // func Entrypoint() { // osthread.Call(FuncA) // Call FuncA on the main operating system thread, block until it returns // // ... // osthread.Go(FuncB) // Schedule FuncB to be called on the main operating system thread // // ... // } package osthread import "runtime" // Start allows arbitrary functions to be run on the main operating system thread. // // Start must be called from the program's main function. Once called, it blocks until entrypoint returns. func Start(entrypoint func()) { done := make(chan any) // Run entrypoint in a separate goroutine. go func() { defer func() { done <- nil }() entrypoint() }() // Call functions in our queue until entrypoint returns. // These functions are called on the main operating system thread. for { select { case fn := <-queue: fn() case <-done: return } } } // Go schedules a function to be run on the main operating system thread, returning immediately. func Go(fn func()) { queue <- fn } // Call schedules a function to be run on the main operating system thread, blocking until it returns. func Call(fn func()) { done := make(chan any) queue <- func() { defer func() { done <- nil }() fn() } <-done } var queue chan func() func init() { runtime.LockOSThread() queue = make(chan func(), runtime.GOMAXPROCS(0)) }