From 90669b9c7fb50b97c69798520faf49cc49a07920 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Fri, 11 Dec 2015 22:48:25 -0500 Subject: [PATCH] More work. --- interop.h | 14 ------------ link_unix.go | 3 ++- main.go | 59 ++++++++++++++++++++++++++++++++++++++++---------- prev/README.md | 1 + 4 files changed, 50 insertions(+), 27 deletions(-) delete mode 100644 interop.h create mode 100644 prev/README.md diff --git a/interop.h b/interop.h deleted file mode 100644 index f45e69a..0000000 --- a/interop.h +++ /dev/null @@ -1,14 +0,0 @@ -// 11 december 2015 - -#ifndef __UI_INTEROP_H__ -#define __UI_INTEROP_H__ - -#include - -extern char *interopInit(void); -extern void interopFreeStr(char *); -extern void interopRun(void); -extern void interopQuit(void); -extern void interopQueueMain(uintptr_t); - -#endif diff --git a/link_unix.go b/link_unix.go index 9d270bf..597dc44 100644 --- a/link_unix.go +++ b/link_unix.go @@ -5,4 +5,5 @@ package ui -// #cgo LDFLAGS: -L. -lui -lpthread +// #cgo LDFLAGS: -L${SRCDIR} -lui -Wl,-rpath=$ORIGIN +import "C" diff --git a/main.go b/main.go index 154192d..f938d45 100644 --- a/main.go +++ b/main.go @@ -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() } diff --git a/prev/README.md b/prev/README.md new file mode 100644 index 0000000..bbb4b26 --- /dev/null +++ b/prev/README.md @@ -0,0 +1 @@ +This directory contains the pre-libui package ui and its various development files. They will be removed at a later date. Do not use this package.