From a35749cb306a3fe9464724db5e3206d2c2d54ff8 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 6 Jan 2025 12:40:15 +0000 Subject: [PATCH] Refactor the goroutine code to internal helpers --- data/binding/queue.go | 22 +---------- internal/async/goroutine.go | 11 ++++++ internal/async/goroutine_desktop.go | 15 +++++++ .../goroutine_goxjs.go} | 2 +- internal/async/goroutine_test.go | 39 +++++++++++++++++++ internal/driver/glfw/driver.go | 3 +- internal/driver/glfw/driver_desktop.go | 9 ----- internal/driver/glfw/driver_test.go | 32 --------------- internal/driver/glfw/loop.go | 1 - 9 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 internal/async/goroutine.go create mode 100644 internal/async/goroutine_desktop.go rename internal/{driver/glfw/driver_goxjs.go => async/goroutine_goxjs.go} (83%) create mode 100644 internal/async/goroutine_test.go diff --git a/data/binding/queue.go b/data/binding/queue.go index e1f1a342a7..d6902837c3 100644 --- a/data/binding/queue.go +++ b/data/binding/queue.go @@ -1,30 +1,12 @@ package binding import ( - "runtime" - "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/async" ) -var mainGoroutineID uint64 - -func init() { - runtime.LockOSThread() - mainGoroutineID = goroutineID() -} - -func goroutineID() (id uint64) { - var buf [30]byte - runtime.Stack(buf[:], false) - for i := 10; buf[i] != ' '; i++ { - id = id*10 + uint64(buf[i]&15) - } - - return id -} - func queueItem(f func()) { - if goroutineID() == mainGoroutineID { + if async.IsMainGoroutine() { f() return } diff --git a/internal/async/goroutine.go b/internal/async/goroutine.go new file mode 100644 index 0000000000..7b699f67b6 --- /dev/null +++ b/internal/async/goroutine.go @@ -0,0 +1,11 @@ +package async + +var mainGoroutineID uint64 + +func init() { + mainGoroutineID = goroutineID() +} + +func IsMainGoroutine() bool { + return goroutineID() == mainGoroutineID +} diff --git a/internal/async/goroutine_desktop.go b/internal/async/goroutine_desktop.go new file mode 100644 index 0000000000..3907669e33 --- /dev/null +++ b/internal/async/goroutine_desktop.go @@ -0,0 +1,15 @@ +//go:build !wasm + +package async + +import "runtime" + +func goroutineID() (id uint64) { + var buf [30]byte + runtime.Stack(buf[:], false) + for i := 10; buf[i] != ' '; i++ { + id = id*10 + uint64(buf[i]&15) + } + + return id +} diff --git a/internal/driver/glfw/driver_goxjs.go b/internal/async/goroutine_goxjs.go similarity index 83% rename from internal/driver/glfw/driver_goxjs.go rename to internal/async/goroutine_goxjs.go index 036de76820..097e905904 100644 --- a/internal/driver/glfw/driver_goxjs.go +++ b/internal/async/goroutine_goxjs.go @@ -1,6 +1,6 @@ //go:build wasm -package glfw +package async func goroutineID() uint64 { return mainGoroutineID diff --git a/internal/async/goroutine_test.go b/internal/async/goroutine_test.go new file mode 100644 index 0000000000..dedadb7679 --- /dev/null +++ b/internal/async/goroutine_test.go @@ -0,0 +1,39 @@ +package async + +import ( + "sync" + "testing" + + "github.com/stretchr/testify/assert" +) + +var mainRoutineID uint64 + +func init() { + mainRoutineID = goroutineID() +} + +func TestGoroutineID(t *testing.T) { + assert.Equal(t, uint64(1), mainRoutineID) + + var childID1, childID2 uint64 + testID1 := goroutineID() + var wg sync.WaitGroup + wg.Add(2) + go func() { + childID1 = goroutineID() + wg.Done() + }() + go func() { + childID2 = goroutineID() + wg.Done() + }() + wg.Wait() + testID2 := goroutineID() + + assert.Equal(t, testID1, testID2) + assert.Greater(t, childID1, uint64(0)) + assert.NotEqual(t, testID1, childID1) + assert.Greater(t, childID2, uint64(0)) + assert.NotEqual(t, childID1, childID2) +} diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index c7cc1a452e..2cfba1e9c4 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -9,6 +9,7 @@ import ( "runtime" "sync" + "fyne.io/fyne/v2/internal/async" "github.com/fyne-io/image/ico" "fyne.io/fyne/v2" @@ -156,7 +157,7 @@ func (d *gLDriver) initFailed(msg string, err error) { } func (d *gLDriver) Run() { - if goroutineID() != mainGoroutineID { + if !async.IsMainGoroutine() { panic("Run() or ShowAndRun() must be called from main goroutine") } diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index 32b6d99921..0649afdaff 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -29,15 +29,6 @@ var ( setup sync.Once ) -func goroutineID() (id uint64) { - var buf [30]byte - runtime.Stack(buf[:], false) - for i := 10; buf[i] != ' '; i++ { - id = id*10 + uint64(buf[i]&15) - } - return id -} - func (d *gLDriver) SetSystemTrayMenu(m *fyne.Menu) { setup.Do(func() { d.trayStart, d.trayStop = systray.RunWithExternalLoop(func() { diff --git a/internal/driver/glfw/driver_test.go b/internal/driver/glfw/driver_test.go index b2b4249456..da584f03e5 100644 --- a/internal/driver/glfw/driver_test.go +++ b/internal/driver/glfw/driver_test.go @@ -3,7 +3,6 @@ package glfw import ( - "sync" "testing" "fyne.io/fyne/v2" @@ -122,34 +121,3 @@ func Test_gLDriver_AbsolutePositionForObject(t *testing.T) { }) } } - -var mainRoutineID uint64 - -func init() { - mainRoutineID = goroutineID() -} - -func TestGoroutineID(t *testing.T) { - assert.Equal(t, uint64(1), mainRoutineID) - - var childID1, childID2 uint64 - testID1 := goroutineID() - var wg sync.WaitGroup - wg.Add(2) - go func() { - childID1 = goroutineID() - wg.Done() - }() - go func() { - childID2 = goroutineID() - wg.Done() - }() - wg.Wait() - testID2 := goroutineID() - - assert.Equal(t, testID1, testID2) - assert.Greater(t, childID1, uint64(0)) - assert.NotEqual(t, testID1, childID1) - assert.Greater(t, childID2, uint64(0)) - assert.NotEqual(t, childID1, childID2) -} diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index ca51b0bd9f..81fe4e2317 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -27,7 +27,6 @@ var initOnce = &sync.Once{} // Arrange that main.main runs on main thread. func init() { runtime.LockOSThread() - mainGoroutineID = goroutineID() } // force a function f to run on the main thread