From 1729e955e16268aea5cb4f3ff5c303866a36eabc Mon Sep 17 00:00:00 2001 From: Geert-Johan Riemer Date: Sat, 16 Feb 2019 19:09:53 +0100 Subject: [PATCH] Fix two race conditions and a type conversion mistake --- flutter/flutter.go | 29 ++++++++++++++--- flutter/flutter_proxy_glfw.go | 32 +++++++++++-------- gutter.go | 59 +++++++++++++++++------------------ 3 files changed, 73 insertions(+), 47 deletions(-) diff --git a/flutter/flutter.go b/flutter/flutter.go index da7481e0..bf1cedac 100644 --- a/flutter/flutter.go +++ b/flutter/flutter.go @@ -8,15 +8,20 @@ package flutter import "C" import ( "encoding/json" + "sync" "unsafe" ) // the current FlutterEngine running (associated with his callback) var flutterEngines []*EngineOpenGL +var flutterEnginesLock sync.RWMutex // SelectEngine return a EngineOpenGL from an index func SelectEngine(index int) *EngineOpenGL { - return flutterEngines[index] + flutterEnginesLock.RLock() + engine := flutterEngines[index] + flutterEnginesLock.RUnlock() + return engine } // NumberOfEngines return the number of engine registered into this embedder @@ -40,6 +45,9 @@ type EngineOpenGL struct { // Flutter Engine. Engine C.FlutterEngine + // index of the engine in the global flutterEngines slice + index int + // Necessary callbacks for rendering. FMakeCurrent func(v unsafe.Pointer) bool FClearCurrent func(v unsafe.Pointer) bool @@ -56,11 +64,24 @@ type EngineOpenGL struct { IcuDataPath string } -// Run launches the Flutter Engine in a background thread. -func (flu *EngineOpenGL) Run(window uintptr, vmArgs []string) Result { - +// NewEngineOpenGL creates an empty EngineOpenGL +// and assigns it an index for global lookup. +func NewEngineOpenGL() *EngineOpenGL { + flu := &EngineOpenGL{} + flutterEnginesLock.Lock() flutterEngines = append(flutterEngines, flu) + flu.index = len(flutterEngines) - 1 + flutterEnginesLock.Unlock() + return flu +} +// Index returns the index of the engine in the global flutterEngines slice +func (flu *EngineOpenGL) Index() int { + return flu.index +} + +// Run launches the Flutter Engine in a background thread. +func (flu *EngineOpenGL) Run(window uintptr, vmArgs []string) Result { args := C.FlutterProjectArgs{ assets_path: C.CString(flu.AssetsPath), main_path: C.CString(""), diff --git a/flutter/flutter_proxy_glfw.go b/flutter/flutter_proxy_glfw.go index c19fd675..1f980ceb 100644 --- a/flutter/flutter_proxy_glfw.go +++ b/flutter/flutter_proxy_glfw.go @@ -18,7 +18,7 @@ import ( // C proxies //export proxy_on_platform_message -func proxy_on_platform_message(message *C.FlutterPlatformMessage, userPointer unsafe.Pointer) C.bool { +func proxy_on_platform_message(message *C.FlutterPlatformMessage, window unsafe.Pointer) C.bool { if message.message != nil { str := C.GoStringN(C.c_str(message.message), C.int(message.message_size)) @@ -30,43 +30,49 @@ func proxy_on_platform_message(message *C.FlutterPlatformMessage, userPointer un Channel: C.GoString(message.channel), ResponseHandle: message.response_handle, } - return C.bool(flutterEngines[0].FPlatfromMessage(FlutterPlatformMessage, userPointer)) + index := *(*int)(glfw.GoWindow(window).GetUserPointer()) + engine := SelectEngine(index) + return C.bool(engine.FPlatfromMessage(FlutterPlatformMessage, window)) } return C.bool(false) - } //export proxy_make_current func proxy_make_current(v unsafe.Pointer) C.bool { w := glfw.GoWindow(v) - index := *(*C.int)(w.GetUserPointer()) - return C.bool(flutterEngines[index].FMakeCurrent(v)) + index := *(*int)(w.GetUserPointer()) + engine := SelectEngine(index) + return C.bool(engine.FMakeCurrent(v)) } //export proxy_clear_current func proxy_clear_current(v unsafe.Pointer) C.bool { w := glfw.GoWindow(v) - index := *(*C.int)(w.GetUserPointer()) - return C.bool(flutterEngines[index].FClearCurrent(v)) + index := *(*int)(w.GetUserPointer()) + engine := SelectEngine(index) + return C.bool(engine.FClearCurrent(v)) } //export proxy_present func proxy_present(v unsafe.Pointer) C.bool { w := glfw.GoWindow(v) - index := *(*C.int)(w.GetUserPointer()) - return C.bool(flutterEngines[index].FPresent(v)) + index := *(*int)(w.GetUserPointer()) + engine := SelectEngine(index) + return C.bool(engine.FPresent(v)) } //export proxy_fbo_callback func proxy_fbo_callback(v unsafe.Pointer) C.uint32_t { w := glfw.GoWindow(v) - index := *(*C.int)(w.GetUserPointer()) - return C.uint32_t(flutterEngines[index].FFboCallback(v)) + index := *(*int)(w.GetUserPointer()) + engine := SelectEngine(index) + return C.uint32_t(engine.FFboCallback(v)) } //export proxy_make_resource_current func proxy_make_resource_current(v unsafe.Pointer) C.bool { w := glfw.GoWindow(v) - index := *(*C.int)(w.GetUserPointer()) - return C.bool(flutterEngines[index].FMakeResourceCurrent(v)) + index := *(*int)(w.GetUserPointer()) + engine := SelectEngine(index) + return C.bool(engine.FMakeResourceCurrent(v)) } diff --git a/gutter.go b/gutter.go index ff74d1ad..585800f1 100644 --- a/gutter.go +++ b/gutter.go @@ -184,33 +184,32 @@ func glfwCharCallback(w *glfw.Window, char rune) { // Flutter Engine func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL { - flutterOGL := flutter.EngineOpenGL{ - // Engine arguments - AssetsPath: c.AssetPath, - IcuDataPath: c.ICUDataPath, - // Render callbacks - FMakeCurrent: func(v unsafe.Pointer) bool { - w := glfw.GoWindow(v) - w.MakeContextCurrent() - return true - }, - FClearCurrent: func(v unsafe.Pointer) bool { - glfw.DetachCurrentContext() - return true - }, - FPresent: func(v unsafe.Pointer) bool { - w := glfw.GoWindow(v) - w.SwapBuffers() - return true - }, - FFboCallback: func(v unsafe.Pointer) int32 { - return 0 - }, - FMakeResourceCurrent: func(v unsafe.Pointer) bool { - return false - }, - PixelRatio: c.PixelRatio, + flutterOGL := flutter.NewEngineOpenGL() + // Engine arguments + flutterOGL.AssetsPath = c.AssetPath + flutterOGL.IcuDataPath = c.ICUDataPath + // Render callbacks + flutterOGL.FMakeCurrent = func(v unsafe.Pointer) bool { + w := glfw.GoWindow(v) + w.MakeContextCurrent() + return true } + flutterOGL.FClearCurrent = func(v unsafe.Pointer) bool { + glfw.DetachCurrentContext() + return true + } + flutterOGL.FPresent = func(v unsafe.Pointer) bool { + w := glfw.GoWindow(v) + w.SwapBuffers() + return true + } + flutterOGL.FFboCallback = func(v unsafe.Pointer) int32 { + return 0 + } + flutterOGL.FMakeResourceCurrent = func(v unsafe.Pointer) bool { + return false + } + flutterOGL.PixelRatio = c.PixelRatio // PlatformMessage flutterOGL.FPlatfromMessage = func(platMessage *flutter.PlatformMessage, window unsafe.Pointer) bool { @@ -221,7 +220,7 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL { // Dispatch the message from the Flutter Engine, to all of the PluginReceivers // having the same flutter.PlatformMessage.Channel name for _, receivers := range c.PlatformMessageReceivers[platMessage.Channel] { - hasDispatched = receivers(platMessage, &flutterOGL, windows) || hasDispatched + hasDispatched = receivers(platMessage, flutterOGL, windows) || hasDispatched } return hasDispatched @@ -232,8 +231,8 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL { updateEditingState(window) } - NbEngine := flutter.NumberOfEngines() - window.SetUserPointer(unsafe.Pointer(&NbEngine)) + flutterOGLIndex := flutterOGL.Index() + window.SetUserPointer(unsafe.Pointer(&flutterOGLIndex)) result := flutterOGL.Run(window.GLFWWindow(), c.VMArguments) if result != flutter.KSuccess { @@ -255,7 +254,7 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL { window.SetFramebufferSizeCallback(glfwWindowSizeCallback) window.SetMouseButtonCallback(glfwMouseButtonCallback) window.SetCharCallback(glfwCharCallback) - return &flutterOGL + return flutterOGL } // Update the TextInput with the current state