package thread import ( "runtime" "sync" ) type fun struct { fn func() done chan struct{} } var dPool = sync.Pool{New: func() any { return make(chan struct{}) }} var fq = make(chan fun, runtime.GOMAXPROCS(0)) var isGraphics = false func init() { runtime.LockOSThread() } // Run is a wrapper for the main function. // Run returns when run (argument) function finishes. func Run(run func()) { done := make(chan struct{}) go func() { run() done <- struct{}{} }() for { select { case f := <-fq: f.fn() f.done <- struct{}{} case <-done: return } } } // Call queues function f on the main thread and blocks until the function f finishes. func Call(f func()) { if !isGraphics { f() return } done := dPool.Get().(chan struct{}) defer dPool.Put(done) fq <- fun{fn: f, done: done} <-done } func Switch(s bool) { isGraphics = s }