forked from joejulian/gio
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:
+9
-17
@@ -5,7 +5,7 @@ package app
|
|||||||
/*
|
/*
|
||||||
#include <Foundation/Foundation.h>
|
#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"))) CFTypeRef gio_createDisplayLink(void);
|
||||||
__attribute__ ((visibility ("hidden"))) void gio_releaseDisplayLink(CFTypeRef dl);
|
__attribute__ ((visibility ("hidden"))) void gio_releaseDisplayLink(CFTypeRef dl);
|
||||||
__attribute__ ((visibility ("hidden"))) int gio_startDisplayLink(CFTypeRef dl);
|
__attribute__ ((visibility ("hidden"))) int gio_startDisplayLink(CFTypeRef dl);
|
||||||
@@ -43,6 +43,7 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"runtime/cgo"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -74,8 +75,6 @@ type displayLink struct {
|
|||||||
// displayLinks maps CFTypeRefs to *displayLinks.
|
// displayLinks maps CFTypeRefs to *displayLinks.
|
||||||
var displayLinks sync.Map
|
var displayLinks sync.Map
|
||||||
|
|
||||||
var mainFuncs = make(chan func(), 1)
|
|
||||||
|
|
||||||
func isMainThread() bool {
|
func isMainThread() bool {
|
||||||
return bool(C.isMainThread())
|
return bool(C.isMainThread())
|
||||||
}
|
}
|
||||||
@@ -86,22 +85,15 @@ func runOnMain(f func()) {
|
|||||||
f()
|
f()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
C.gio_runOnMain(C.uintptr_t(cgo.NewHandle(f)))
|
||||||
mainFuncs <- f
|
|
||||||
C.gio_wakeupMainThread()
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//export gio_dispatchMainFuncs
|
//export gio_runFunc
|
||||||
func gio_dispatchMainFuncs() {
|
func gio_runFunc(h C.uintptr_t) {
|
||||||
for {
|
handle := cgo.Handle(h)
|
||||||
select {
|
defer handle.Delete()
|
||||||
case f := <-mainFuncs:
|
f := handle.Value().(func())
|
||||||
f()
|
f()
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsstringToString converts a NSString to a Go string.
|
// nsstringToString converts a NSString to a Go string.
|
||||||
|
|||||||
+2
-2
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
void gio_wakeupMainThread(void) {
|
void gio_runOnMain(uintptr_t h) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
gio_dispatchMainFuncs();
|
gio_runFunc(h);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user