app: [macOS/iOS] simplify running functions in the main thread

Using cgo.Handle allows us to pass a reference to a Go function through
the GCD API for running main thread code, saving a goroutine and a channel.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2025-09-10 22:55:16 +02:00
parent 4c0e526c0b
commit 6553915e59
2 changed files with 11 additions and 19 deletions
+9 -17
View File
@@ -5,7 +5,7 @@ package app
/*
#include <Foundation/Foundation.h>
__attribute__ ((visibility ("hidden"))) void gio_wakeupMainThread(void);
__attribute__ ((visibility ("hidden"))) void gio_runOnMain(uintptr_t h);
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createDisplayLink(void);
__attribute__ ((visibility ("hidden"))) void gio_releaseDisplayLink(CFTypeRef dl);
__attribute__ ((visibility ("hidden"))) int gio_startDisplayLink(CFTypeRef dl);
@@ -43,6 +43,7 @@ import "C"
import (
"errors"
"runtime/cgo"
"sync"
"sync/atomic"
"time"
@@ -74,8 +75,6 @@ type displayLink struct {
// displayLinks maps CFTypeRefs to *displayLinks.
var displayLinks sync.Map
var mainFuncs = make(chan func(), 1)
func isMainThread() bool {
return bool(C.isMainThread())
}
@@ -86,22 +85,15 @@ func runOnMain(f func()) {
f()
return
}
go func() {
mainFuncs <- f
C.gio_wakeupMainThread()
}()
C.gio_runOnMain(C.uintptr_t(cgo.NewHandle(f)))
}
//export gio_dispatchMainFuncs
func gio_dispatchMainFuncs() {
for {
select {
case f := <-mainFuncs:
f()
default:
return
}
}
//export gio_runFunc
func gio_runFunc(h C.uintptr_t) {
handle := cgo.Handle(h)
defer handle.Delete()
f := handle.Value().(func())
f()
}
// nsstringToString converts a NSString to a Go string.
+2 -2
View File
@@ -4,8 +4,8 @@
#include "_cgo_export.h"
void gio_wakeupMainThread(void) {
void gio_runOnMain(uintptr_t h) {
dispatch_async(dispatch_get_main_queue(), ^{
gio_dispatchMainFuncs();
gio_runFunc(h);
});
}