diff options
| author | Pietro Gagliardi <[email protected]> | 2015-12-11 22:48:25 -0500 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2015-12-11 22:48:25 -0500 |
| commit | 90669b9c7fb50b97c69798520faf49cc49a07920 (patch) | |
| tree | b1fe84a46a0f09d91ae6894df707a53ad81c086a /main.go | |
| parent | eef149060f7306c7eccc8855dceee68ccd45026e (diff) | |
More work.
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 59 |
1 files changed, 47 insertions, 12 deletions
@@ -3,10 +3,20 @@ package ui import ( + "runtime" "errors" + "sync" + "unsafe" ) -// #include "interop.h" +// #include "ui.h" +// extern void doQueued(void *); +// /* I forgot how dumb cgo is... ./main.go:73: cannot use _Cgo_ptr(_Cfpvar_fp_doQueued) (type unsafe.Pointer) as type *[0]byte in argument to _Cfunc_uiQueueMain */ +// /* I'm pretty sure this worked before... */ +// static inline void realQueueMain(void *x) +// { +// uiQueueMain(doQueued, x); +// } import "C" // Main initializes package ui, runs f to set up the program, @@ -23,23 +33,35 @@ func Main(f func()) error { } func start(errchan chan error, f func()) { - estr := C.interopInit() - if estr != "" { + runtime.LockOSThread() + + // TODO HEAP SAFETY + opts := C.uiInitOptions{} + estr := C.uiInit(&opts) + if estr != nil { errchan <- errors.New(C.GoString(estr)) - C.interopFreeStr(estr) + C.uiFreeInitError(estr) return } QueueMain(f) - C.interopRun() + C.uiMain() errchan <- nil } // Quit queues an exit from the GUI thread. It does not exit the // program. Quit must be called from the GUI thread. func Quit() { - C.interopQuit() + C.uiQuit() } +// These prevent the passing of Go functions into C land. +// TODO make an actual sparse list instead of this monotonic map thingy +var ( + qmmap = make(map[uintptr]func()) + qmcurrent = uintptr(0) + qmlock sync.Mutex +) + // QueueMain queues f to be executed on the GUI thread when // next possible. It returns immediately; that is, it does not wait // for the function to actually be executed. QueueMain is the only @@ -48,13 +70,26 @@ func Quit() { // goroutines and the GUI thread. Calling QueueMain after Quit // has been called results in undefined behavior. func QueueMain(f func()) { - n := interoperAdd(f) - C.interopQueueMain(n) + qmlock.Lock() + defer qmlock.Unlock() + + n := qmcurrent + qmcurrent++ + qmmap[n] = f + C.realQueueMain(unsafe.Pointer(n)) } -//export interopDoQueued -func interopDoQueued(n C.uintptr_t) { - ff := interoperTake(n) - f := ff.(func()) +//export doQueued +func doQueued(nn unsafe.Pointer) { + qmlock.Lock() + + n := uintptr(nn) + f := qmmap[n] + delete(qmmap, n) + + // allow uiQueueMain() to be called by a queued function + // TODO explicitly allow this in libui too + qmlock.Unlock() + f() } |
