From 7a36acbf9ba80f4480e30701ab3976aaf69e24a0 Mon Sep 17 00:00:00 2001 From: Judah Caruso Date: Tue, 18 Nov 2025 18:45:35 -0700 Subject: [PATCH] osthread: init --- osthread/osthread.go | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 osthread/osthread.go diff --git a/osthread/osthread.go b/osthread/osthread.go new file mode 100644 index 0000000..8be5ec2 --- /dev/null +++ b/osthread/osthread.go @@ -0,0 +1,70 @@ +// 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)) +}