From 84c727bda67c343b82d3e2c548f692d420d85f8f Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:01:21 +0100 Subject: [PATCH 01/22] Use the new math.MaxInt contant in table --- widget/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/table.go b/widget/table.go index d492487fa3..85333506cb 100644 --- a/widget/table.go +++ b/widget/table.go @@ -13,7 +13,7 @@ import ( "fyne.io/fyne/v2/theme" ) -const noCellMatch = math.MaxInt32 // TODO make this MaxInt once we move to newer Go version +const noCellMatch = math.MaxInt // allTableCellsID represents all table cells when refreshing requested cells var allTableCellsID = TableCellID{-1, -1} From b323f49abb67381e245b6b3ff4254ce8d39aa756 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:13:07 +0100 Subject: [PATCH 02/22] Replace some usages of IndexByte with strings.Cut --- internal/repository/mime/mime.go | 11 ++++------- storage/filter.go | 7 +------ storage/repository/parse.go | 8 +++----- storage/repository/uri.go | 8 ++------ 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/internal/repository/mime/mime.go b/internal/repository/mime/mime.go index ef39897531..e3281d6301 100644 --- a/internal/repository/mime/mime.go +++ b/internal/repository/mime/mime.go @@ -4,13 +4,10 @@ import "strings" // Split spits the mimetype into its main type and subtype. func Split(mimeTypeFull string) (mimeType, mimeSubType string) { - // Replace with strings.Cut() when Go 1.18 is our new base version. - separatorIndex := strings.IndexByte(mimeTypeFull, '/') - if separatorIndex == -1 || mimeTypeFull[separatorIndex+1:] == "" { - return "", "" // Empty or only one part. Ignore. + mimeType, mimeSubType, ok := strings.Cut(mimeTypeFull, "/") + if !ok || mimeSubType == "" { + return "", "" } - mimeType = mimeTypeFull[:separatorIndex] - mimeSubType = mimeTypeFull[separatorIndex+1:] - return + return mimeType, mimeSubType } diff --git a/storage/filter.go b/storage/filter.go index bcc9adac05..3476bd49c1 100644 --- a/storage/filter.go +++ b/storage/filter.go @@ -50,12 +50,7 @@ func (mt *MimeTypeFileFilter) Matches(uri fyne.URI) bool { continue } - // Replace with strings.Cut() when Go 1.18 is our new base version. - subTypeSeparatorIndex := strings.IndexByte(mSubType, ';') - if subTypeSeparatorIndex != -1 { - mSubType = mSubType[:subTypeSeparatorIndex] - } - + mSubType, _, _ = strings.Cut(mSubType, ";") if mType == mimeType && (mSubType == mimeSubType || mSubType == "*") { return true } diff --git a/storage/repository/parse.go b/storage/repository/parse.go index db4e25962e..6da6e9d4ab 100644 --- a/storage/repository/parse.go +++ b/storage/repository/parse.go @@ -40,14 +40,12 @@ func NewFileURI(path string) fyne.URI { // Since: 2.0 func ParseURI(s string) (fyne.URI, error) { // Extract the scheme. - colonIndex := strings.IndexByte(s, ':') - if colonIndex <= 0 { + scheme, _, ok := strings.Cut(s, ":") + if !ok { return nil, errors.New("invalid URI, scheme must be present") } - scheme := strings.ToLower(s[:colonIndex]) - - if scheme == "file" { + if strings.EqualFold(scheme, "file") { // Does this really deserve to be special? In principle, the // purpose of this check is to pass it to NewFileURI, which // allows platform path seps in the URI (against the RFC, but diff --git a/storage/repository/uri.go b/storage/repository/uri.go index 44a5416b19..c687302181 100644 --- a/storage/repository/uri.go +++ b/storage/repository/uri.go @@ -49,12 +49,8 @@ func (u *uri) MimeType() string { } } - // Replace with strings.Cut() when Go 1.18 is our new base version. - semicolonIndex := strings.IndexByte(mimeTypeFull, ';') - if semicolonIndex == -1 { - return mimeTypeFull - } - return mimeTypeFull[:semicolonIndex] + mimeType, _, _ := strings.Cut(mimeTypeFull, ";") + return mimeType } func (u *uri) Scheme() string { From 5af278bdf664324c0b277ba3399ac97ce1bab5f2 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:58:39 +0100 Subject: [PATCH 03/22] Start using new Go 1.19 atomic APIs --- app.go | 6 ++-- dialog/color_channel.go | 8 +++--- internal/animation/animation.go | 6 ++-- internal/app/lifecycle.go | 47 ++++++++++++++++++-------------- internal/cache/base.go | 7 +++-- internal/driver/common/canvas.go | 6 ++-- internal/driver/glfw/driver.go | 6 ++-- internal/driver/glfw/loop.go | 6 ++-- internal/driver/mobile/driver.go | 4 +-- 9 files changed, 51 insertions(+), 45 deletions(-) diff --git a/app.go b/app.go index d36d326cf4..bffcf9c1ff 100644 --- a/app.go +++ b/app.go @@ -83,7 +83,7 @@ type App interface { // app contains an App variable, but due to atomic.Value restrictions on // interfaces we need to use an indirect type, i.e. appContainer. -var app atomic.Value // appContainer +var app atomic.Pointer[appContainer] // appContainer // appContainer is a dummy container that holds an App instance. This // struct exists to guarantee that atomic.Value can store objects with @@ -94,7 +94,7 @@ type appContainer struct { // SetCurrentApp is an internal function to set the app instance currently running. func SetCurrentApp(current App) { - app.Store(appContainer{current}) + app.Store(&appContainer{current}) } // CurrentApp returns the current application, for which there is only 1 per process. @@ -104,7 +104,7 @@ func CurrentApp() App { LogError("Attempt to access current Fyne app when none is started", nil) return nil } - return (val).(appContainer).current + return val.current } // AppMetadata captures the build metadata for an application. diff --git a/dialog/color_channel.go b/dialog/color_channel.go index 4f5d9f6e3c..839feb191f 100644 --- a/dialog/color_channel.go +++ b/dialog/color_channel.go @@ -152,7 +152,7 @@ func (e *colorChannelEntry) MinSize() fyne.Size { type userChangeEntry struct { widget.Entry - userTyped uint32 // atomic, 0 == false, 1 == true + userTyped atomic.Bool } func newUserChangeEntry(text string) *userChangeEntry { @@ -164,7 +164,7 @@ func newUserChangeEntry(text string) *userChangeEntry { func (e *userChangeEntry) setOnChanged(onChanged func(s string)) { e.Entry.OnChanged = func(text string) { - if !atomic.CompareAndSwapUint32(&e.userTyped, 1, 0) { + if !e.userTyped.CompareAndSwap(true, false) { return } if onChanged != nil { @@ -175,11 +175,11 @@ func (e *userChangeEntry) setOnChanged(onChanged func(s string)) { } func (e *userChangeEntry) TypedRune(r rune) { - atomic.StoreUint32(&e.userTyped, 1) + e.userTyped.Store(true) e.Entry.TypedRune(r) } func (e *userChangeEntry) TypedKey(ev *fyne.KeyEvent) { - atomic.StoreUint32(&e.userTyped, 1) + e.userTyped.Store(true) e.Entry.TypedKey(ev) } diff --git a/internal/animation/animation.go b/internal/animation/animation.go index 68eccec1d9..6d3a1712e1 100644 --- a/internal/animation/animation.go +++ b/internal/animation/animation.go @@ -14,7 +14,7 @@ type anim struct { reverse bool start time.Time total int64 - stopped uint32 // atomic, 0 == false 1 == true + stopped atomic.Bool } func newAnim(a *fyne.Animation) *anim { @@ -25,9 +25,9 @@ func newAnim(a *fyne.Animation) *anim { } func (a *anim) setStopped() { - atomic.StoreUint32(&a.stopped, 1) + a.stopped.Store(true) } func (a *anim) isStopped() bool { - return atomic.LoadUint32(&a.stopped) == 1 + return a.stopped.Load() } diff --git a/internal/app/lifecycle.go b/internal/app/lifecycle.go index b8b6fe70a9..71c826d93a 100644 --- a/internal/app/lifecycle.go +++ b/internal/app/lifecycle.go @@ -12,10 +12,10 @@ var _ fyne.Lifecycle = (*Lifecycle)(nil) // // Since: 2.1 type Lifecycle struct { - onForeground atomic.Value // func() - onBackground atomic.Value // func() - onStarted atomic.Value // func() - onStopped atomic.Value // func() + onForeground atomic.Pointer[func()] + onBackground atomic.Pointer[func()] + onStarted atomic.Pointer[func()] + onStopped atomic.Pointer[func()] onStoppedHookExecuted func() } @@ -28,57 +28,64 @@ func (l *Lifecycle) SetOnStoppedHookExecuted(f func()) { // SetOnEnteredForeground hooks into the the app becoming foreground. func (l *Lifecycle) SetOnEnteredForeground(f func()) { - l.onForeground.Store(f) + l.onForeground.Store(&f) } // SetOnExitedForeground hooks into the app having moved to the background. // Depending on the platform it may still be visible but will not receive keyboard events. // On some systems hover or desktop mouse move events may still occur. func (l *Lifecycle) SetOnExitedForeground(f func()) { - l.onBackground.Store(f) + l.onBackground.Store(&f) } // SetOnStarted hooks into an event that says the app is now running. func (l *Lifecycle) SetOnStarted(f func()) { - l.onStarted.Store(f) + l.onStarted.Store(&f) } // SetOnStopped hooks into an event that says the app is no longer running. func (l *Lifecycle) SetOnStopped(f func()) { - l.onStopped.Store(f) + l.onStopped.Store(&f) } // TriggerEnteredForeground will call the focus gained hook, if one is registered. func (l *Lifecycle) TriggerEnteredForeground() { - f := l.onForeground.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onForeground.Load() + if f == nil { + return } + + f() } // TriggerExitedForeground will call the focus lost hook, if one is registered. func (l *Lifecycle) TriggerExitedForeground() { - f := l.onBackground.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onBackground.Load() + if f == nil { + return } + + f() } // TriggerStarted will call the started hook, if one is registered. func (l *Lifecycle) TriggerStarted() { - f := l.onStarted.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onStarted.Load() + if f == nil { + return } + + f() } // TriggerStopped will call the stopped hook, if one is registered, // and an internal stopped hook after that. func (l *Lifecycle) TriggerStopped() { - f := l.onStopped.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onStopped.Load() + if f != nil { + f() } + if l.onStoppedHookExecuted != nil { l.onStoppedHookExecuted() } diff --git a/internal/cache/base.go b/internal/cache/base.go index 422a08503d..21dc8f70dd 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -215,7 +215,7 @@ func matchesACanvas(cinfo *canvasInfo, canvases []fyne.Canvas) bool { } type expiringCache struct { - expires atomic.Value // time.Time + expires atomic.Pointer[time.Time] } // isExpired check if the cache data is expired. @@ -224,12 +224,13 @@ func (c *expiringCache) isExpired(now time.Time) bool { if t == nil { return (time.Time{}).Before(now) } - return t.(time.Time).Before(now) + return t.Before(now) } // setAlive updates expiration time. func (c *expiringCache) setAlive() { - c.expires.Store(timeNow().Add(cacheDuration)) + expirationTIme := timeNow().Add(cacheDuration) + c.expires.Store(&expirationTIme) } type expiringCacheNoLock struct { diff --git a/internal/driver/common/canvas.go b/internal/driver/common/canvas.go index c70c0f13ff..594a436718 100644 --- a/internal/driver/common/canvas.go +++ b/internal/driver/common/canvas.go @@ -49,7 +49,7 @@ type Canvas struct { // the refreshQueue is an unbounded queue which is bale to cache // arbitrary number of fyne.CanvasObject for the rendering. refreshQueue *async.CanvasObjectQueue - dirty uint32 // atomic + dirty atomic.Bool mWindowHeadTree, contentTree, menuTree *renderCacheTree } @@ -380,12 +380,12 @@ func (c *Canvas) SetContentTreeAndFocusMgr(content fyne.CanvasObject) { // CheckDirtyAndClear returns true if the canvas is dirty and // clears the dirty state atomically. func (c *Canvas) CheckDirtyAndClear() bool { - return atomic.SwapUint32(&c.dirty, 0) != 0 + return c.dirty.Swap(false) } // SetDirty sets canvas dirty flag atomically. func (c *Canvas) SetDirty() { - atomic.AddUint32(&c.dirty, 1) + c.dirty.Store(true) } // SetMenuTreeAndFocusMgr sets menu tree and focus manager. diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index 6a44a1c45d..7c68ff7486 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -8,7 +8,6 @@ import ( "os" "runtime" "sync" - "sync/atomic" "time" "github.com/fyne-io/image/ico" @@ -109,7 +108,7 @@ func (d *gLDriver) Quit() { } // Only call close once to avoid panic. - if atomic.CompareAndSwapUint32(&running, 1, 0) { + if running.CompareAndSwap(true, false) { close(d.done) } } @@ -154,8 +153,7 @@ func (d *gLDriver) windowList() []fyne.Window { func (d *gLDriver) initFailed(msg string, err error) { logError(msg, err) - onMain := atomic.LoadUint32(&running) == 0 - if onMain { + if !running.Load() { d.Quit() } else { os.Exit(1) diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index 7d2fab3228..6bfdf41caa 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -28,7 +28,7 @@ type drawData struct { // channel for queuing functions on the main thread var funcQueue = make(chan funcData) var drawFuncQueue = make(chan drawData) -var running uint32 // atomic bool, 0 or 1 +var running atomic.Bool var initOnce = &sync.Once{} // Arrange that main.main runs on main thread. @@ -41,7 +41,7 @@ func init() { func runOnMain(f func()) { // If we are on main just execute - otherwise add it to the main queue and wait. // The "running" variable is normally false when we are on the main thread. - if onMain := atomic.LoadUint32(&running) == 0; onMain { + if !running.Load() { f() return } @@ -105,7 +105,7 @@ func (d *gLDriver) drawSingleFrame() { } func (d *gLDriver) runGL() { - if !atomic.CompareAndSwapUint32(&running, 0, 1) { + if !running.CompareAndSwap(false, true) { return // Run was called twice. } close(d.waitForStart) // Signal that execution can continue. diff --git a/internal/driver/mobile/driver.go b/internal/driver/mobile/driver.go index 4173cd3ad2..1629894ab6 100644 --- a/internal/driver/mobile/driver.go +++ b/internal/driver/mobile/driver.go @@ -57,7 +57,7 @@ type mobileDriver struct { theme fyne.ThemeVariant onConfigChanged func(*Configuration) painting bool - running uint32 // atomic, 1 == running, 0 == stopped + running atomic.Bool } // Declare conformity with Driver @@ -141,7 +141,7 @@ func (d *mobileDriver) Quit() { } func (d *mobileDriver) Run() { - if !atomic.CompareAndSwapUint32(&d.running, 0, 1) { + if !d.running.CompareAndSwap(false, true) { return // Run was called twice. } From 2334c7485a30a7cade0c950818e21fbbb5cd7e68 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:59:52 +0100 Subject: [PATCH 04/22] Fix scheme not being lowercase --- storage/repository/parse.go | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/repository/parse.go b/storage/repository/parse.go index 6da6e9d4ab..33ff36cd5e 100644 --- a/storage/repository/parse.go +++ b/storage/repository/parse.go @@ -65,6 +65,7 @@ func ParseURI(s string) (fyne.URI, error) { return NewFileURI(path), nil } + scheme = strings.ToLower(scheme) repo, err := ForScheme(scheme) if err == nil { // If the repository registered for this scheme implements a parser From dd7943c9711e2d4786096603104aa6ceb0e567b4 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:14:15 +0100 Subject: [PATCH 05/22] Avoid copy of lock --- internal/cache/base.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cache/base.go b/internal/cache/base.go index 21dc8f70dd..8f9f7cb3ab 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -215,7 +215,7 @@ func matchesACanvas(cinfo *canvasInfo, canvases []fyne.Canvas) bool { } type expiringCache struct { - expires atomic.Pointer[time.Time] + expires atomic.Value // time.time } // isExpired check if the cache data is expired. @@ -224,7 +224,7 @@ func (c *expiringCache) isExpired(now time.Time) bool { if t == nil { return (time.Time{}).Before(now) } - return t.Before(now) + return t.(time.Time).Before(now) } // setAlive updates expiration time. From 580e8e27709351db24a0b48912f14d22db473db9 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:22:26 +0100 Subject: [PATCH 06/22] More usages of new atomic APIs --- internal/async/gen.go | 9 ++--- internal/async/queue_canvasobject.go | 7 ++-- internal/async/queue_pure_canvasobject.go | 41 +++++++++++++++++++++ internal/async/queue_unsafe_canvasobject.go | 2 +- internal/driver/glfw/window_test.go | 12 +++--- widget/bind_helper.go | 12 +++--- 6 files changed, 62 insertions(+), 21 deletions(-) create mode 100755 internal/async/queue_pure_canvasobject.go diff --git a/internal/async/gen.go b/internal/async/gen.go index fb95af7c83..b31a3a68a9 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -51,7 +51,6 @@ func main() { Name: "CanvasObject", Imports: `import ( "sync" - "sync/atomic" "fyne.io/fyne/v2" )`, @@ -204,7 +203,7 @@ package async type {{.Name}}Queue struct { head unsafe.Pointer tail unsafe.Pointer - len uint64 + len atomic.Uint64 } // New{{.Name}}Queue returns a queue for caching values. @@ -254,7 +253,7 @@ func (q *{{.Name}}Queue) In(v {{.Type}}) { if lastnext == nil { if cas{{.Name}}Item(&last.next, lastnext, i) { cas{{.Name}}Item(&q.tail, last, i) - atomic.AddUint64(&q.len, 1) + q.len.Add(1) return } } else { @@ -281,7 +280,7 @@ func (q *{{.Name}}Queue) Out() {{.Type}} { } else { v := firstnext.v if cas{{.Name}}Item(&q.head, first, firstnext) { - atomic.AddUint64(&q.len, ^uint64(0)) + q.len.Add(^uint64(0)) item{{.Name}}Pool.Put(first) return v } @@ -292,6 +291,6 @@ func (q *{{.Name}}Queue) Out() {{.Type}} { // Len returns the length of the queue. func (q *{{.Name}}Queue) Len() uint64 { - return atomic.LoadUint64(&q.len) + return q.len.Load() } `)) diff --git a/internal/async/queue_canvasobject.go b/internal/async/queue_canvasobject.go index c0acb5c718..1af42f28df 100755 --- a/internal/async/queue_canvasobject.go +++ b/internal/async/queue_canvasobject.go @@ -4,7 +4,6 @@ package async import ( "sync" - "sync/atomic" "fyne.io/fyne/v2" ) @@ -27,7 +26,7 @@ func (q *CanvasObjectQueue) In(v fyne.CanvasObject) { if lastnext == nil { if casCanvasObjectItem(&last.next, lastnext, i) { casCanvasObjectItem(&q.tail, last, i) - atomic.AddUint64(&q.len, 1) + q.len.Add(1) return } } else { @@ -54,7 +53,7 @@ func (q *CanvasObjectQueue) Out() fyne.CanvasObject { } else { v := firstnext.v if casCanvasObjectItem(&q.head, first, firstnext) { - atomic.AddUint64(&q.len, ^uint64(0)) + q.len.Add(^uint64(0)) itemCanvasObjectPool.Put(first) return v } @@ -65,5 +64,5 @@ func (q *CanvasObjectQueue) Out() fyne.CanvasObject { // Len returns the length of the queue. func (q *CanvasObjectQueue) Len() uint64 { - return atomic.LoadUint64(&q.len) + return q.len.Load() } diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go new file mode 100755 index 0000000000..05bd739014 --- /dev/null +++ b/internal/async/queue_pure_canvasobject.go @@ -0,0 +1,41 @@ +// Code generated by go run gen.go; DO NOT EDIT. +//go:build js +// +build js + +package async + +import ( + "fyne.io/fyne/v2" +) + +// CanvasObjectQueue implements lock-free FIFO freelist based queue. +// +// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 +type CanvasObjectQueue struct { + head *itemCanvasObject + tail *itemCanvasObject + len atomic.Uint64 +} + +// NewCanvasObjectQueue returns a queue for caching values. +func NewCanvasObjectQueue() *CanvasObjectQueue { + head := &itemCanvasObject{next: nil, v: nil} + return &CanvasObjectQueue{ + tail: head, + head: head, + } +} + +type itemCanvasObject struct { + next *itemCanvasObject + v fyne.CanvasObject +} + +func loadCanvasObjectItem(p **itemCanvasObject) *itemCanvasObject { + return *p +} + +func casCanvasObjectItem(p **itemCanvasObject, _, new *itemCanvasObject) bool { + *p = new + return true +} diff --git a/internal/async/queue_unsafe_canvasobject.go b/internal/async/queue_unsafe_canvasobject.go index c78247ddcc..5fbb99d26a 100755 --- a/internal/async/queue_unsafe_canvasobject.go +++ b/internal/async/queue_unsafe_canvasobject.go @@ -15,7 +15,7 @@ import ( type CanvasObjectQueue struct { head unsafe.Pointer tail unsafe.Pointer - len uint64 + len atomic.Uint64 } // NewCanvasObjectQueue returns a queue for caching values. diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index c0e8718ed5..15ebd22273 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1220,14 +1220,14 @@ func TestWindow_TappedAndDoubleTapped(t *testing.T) { w := createWindow("Test").(*window) waitSingleTapped := make(chan struct{}) waitDoubleTapped := make(chan struct{}) - tapped := int32(0) // atomic + tapped := atomic.Int32{} but := newDoubleTappableButton() but.OnTapped = func() { - atomic.StoreInt32(&tapped, 1) + tapped.Store(1) waitSingleTapped <- struct{}{} } but.onDoubleTap = func() { - atomic.StoreInt32(&tapped, 2) + tapped.Store(2) waitDoubleTapped <- struct{}{} } w.SetContent(container.NewBorder(nil, nil, nil, nil, but)) @@ -1240,8 +1240,8 @@ func TestWindow_TappedAndDoubleTapped(t *testing.T) { w.WaitForEvents() time.Sleep(500 * time.Millisecond) - assert.Equal(t, int32(1), atomic.LoadInt32(&tapped), "Single tap should have fired") - atomic.StoreInt32(&tapped, 0) + assert.Equal(t, int32(1), tapped.Load(), "Single tap should have fired") + tapped.Store(0) w.mouseClicked(w.viewport, glfw.MouseButton1, glfw.Press, 0) w.mouseClicked(w.viewport, glfw.MouseButton1, glfw.Release, 0) @@ -1252,7 +1252,7 @@ func TestWindow_TappedAndDoubleTapped(t *testing.T) { w.WaitForEvents() time.Sleep(500 * time.Millisecond) - assert.Equal(t, int32(2), atomic.LoadInt32(&tapped), "Double tap should have fired") + assert.Equal(t, int32(2), tapped.Load(), "Double tap should have fired") } func TestWindow_MouseEventContainsModifierKeys(t *testing.T) { diff --git a/widget/bind_helper.go b/widget/bind_helper.go index 9f02fc273a..069c5ed0cf 100644 --- a/widget/bind_helper.go +++ b/widget/bind_helper.go @@ -10,7 +10,7 @@ import ( // basicBinder stores a DataItem and a function to be called when it changes. // It provides a convenient way to replace data and callback independently. type basicBinder struct { - callback atomic.Value // func(binding.DataItem) + callback atomic.Pointer[func(binding.DataItem)] dataListenerPairLock sync.RWMutex dataListenerPair annotatedListener // access guarded by dataListenerPairLock @@ -19,10 +19,12 @@ type basicBinder struct { // Bind replaces the data item whose changes are tracked by the callback function. func (binder *basicBinder) Bind(data binding.DataItem) { listener := binding.NewDataListener(func() { // NB: listener captures `data` but always calls the up-to-date callback - f := binder.callback.Load() - if fn, ok := f.(func(binding.DataItem)); ok && fn != nil { - fn(data) + f := *binder.callback.Load() + if f == nil { + return } + + f(data) }) data.AddListener(listener) listenerInfo := annotatedListener{ @@ -47,7 +49,7 @@ func (binder *basicBinder) CallWithData(f func(data binding.DataItem)) { // SetCallback replaces the function to be called when the data changes. func (binder *basicBinder) SetCallback(f func(data binding.DataItem)) { - binder.callback.Store(f) + binder.callback.Store(&f) } // Unbind requests the callback to be no longer called when the previously bound From f0aae53b4867efe53fb950dc5cc87112ca1e7e35 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:30:32 +0100 Subject: [PATCH 07/22] Fix a bad revert --- internal/cache/base.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/cache/base.go b/internal/cache/base.go index 8f9f7cb3ab..204e8f4604 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -229,8 +229,7 @@ func (c *expiringCache) isExpired(now time.Time) bool { // setAlive updates expiration time. func (c *expiringCache) setAlive() { - expirationTIme := timeNow().Add(cacheDuration) - c.expires.Store(&expirationTIme) + c.expires.Store(timeNow().Add(cacheDuration)) } type expiringCacheNoLock struct { From 5eb3608bf16c100c627b617301e51bea68b376d7 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:35:49 +0100 Subject: [PATCH 08/22] No need to use execabs any more --- app/app_darwin.go | 4 ++-- app/app_desktop_darwin.go | 5 ++--- app/app_windows.go | 6 +++--- app/app_xdg.go | 4 ++-- dialog/file_xdg.go | 7 +++---- theme/gen.go | 5 ++--- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/app/app_darwin.go b/app/app_darwin.go index 8e6e08668f..0feabf3feb 100644 --- a/app/app_darwin.go +++ b/app/app_darwin.go @@ -16,11 +16,11 @@ void sendNotification(char *title, char *content); import "C" import ( "fmt" + "os/exec" "strings" "unsafe" "fyne.io/fyne/v2" - "golang.org/x/sys/execabs" ) func (a *fyneApp) SendNotification(n *fyne.Notification) { @@ -53,7 +53,7 @@ func fallbackNotification(title, content string) { template := `display notification "%s" with title "%s"` script := fmt.Sprintf(template, escapeNotificationString(content), escapeNotificationString(title)) - err := execabs.Command("osascript", "-e", script).Start() + err := exec.Command("osascript", "-e", script).Start() if err != nil { fyne.LogError("Failed to launch darwin notify script", err) } diff --git a/app/app_desktop_darwin.go b/app/app_desktop_darwin.go index eb93777e8b..7305e95996 100644 --- a/app/app_desktop_darwin.go +++ b/app/app_desktop_darwin.go @@ -17,10 +17,9 @@ import "C" import ( "net/url" "os" + "os/exec" "path/filepath" - "golang.org/x/sys/execabs" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" ) @@ -54,7 +53,7 @@ func rootConfigDir() string { } func (a *fyneApp) OpenURL(url *url.URL) error { - cmd := execabs.Command("open", url.String()) + cmd := exec.Command("open", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Run() } diff --git a/app/app_windows.go b/app/app_windows.go index 60d9b0a166..718cb6f348 100644 --- a/app/app_windows.go +++ b/app/app_windows.go @@ -7,11 +7,11 @@ import ( "fmt" "net/url" "os" + "os/exec" "path/filepath" "strings" "syscall" - "golang.org/x/sys/execabs" "golang.org/x/sys/windows/registry" "fyne.io/fyne/v2" @@ -62,7 +62,7 @@ func rootConfigDir() string { } func (a *fyneApp) OpenURL(url *url.URL) error { - cmd := execabs.Command("rundll32", "url.dll,FileProtocolHandler", url.String()) + cmd := exec.Command("rundll32", "url.dll,FileProtocolHandler", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Run() } @@ -112,7 +112,7 @@ func runScript(name, script string) { defer os.Remove(tmpFilePath) launch := "(Get-Content -Encoding UTF8 -Path " + tmpFilePath + " -Raw) | Invoke-Expression" - cmd := execabs.Command("PowerShell", "-ExecutionPolicy", "Bypass", launch) + cmd := exec.Command("PowerShell", "-ExecutionPolicy", "Bypass", launch) cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} err = cmd.Run() if err != nil { diff --git a/app/app_xdg.go b/app/app_xdg.go index de39cecead..6d31a996a3 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -10,13 +10,13 @@ package app import ( "net/url" "os" + "os/exec" "path/filepath" "sync" "github.com/godbus/dbus/v5" "github.com/rymdport/portal/notification" "github.com/rymdport/portal/openuri" - "golang.org/x/sys/execabs" "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal/build" @@ -38,7 +38,7 @@ func (a *fyneApp) OpenURL(url *url.URL) error { return err } - cmd := execabs.Command("xdg-open", url.String()) + cmd := exec.Command("xdg-open", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Start() } diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 824aa1bce3..d73b6f781f 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -9,20 +9,19 @@ package dialog import ( "fmt" "os" + "os/exec" "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" - - "golang.org/x/sys/execabs" ) func getFavoriteLocation(homeURI fyne.URI, name, fallbackName string) (fyne.URI, error) { cmdName := "xdg-user-dir" - if _, err := execabs.LookPath(cmdName); err != nil { + if _, err := exec.LookPath(cmdName); err != nil { return storage.Child(homeURI, fallbackName) // no lookup possible } - cmd := execabs.Command(cmdName, name) + cmd := exec.Command(cmdName, name) loc, err := cmd.Output() if err != nil { return storage.Child(homeURI, fallbackName) diff --git a/theme/gen.go b/theme/gen.go index 11a2cb50ba..e4a86ae23f 100644 --- a/theme/gen.go +++ b/theme/gen.go @@ -9,13 +9,12 @@ import ( "go/format" "io" "os" + "os/exec" "path" "path/filepath" "runtime" "strings" - "golang.org/x/sys/execabs" - "fyne.io/fyne/v2" ) @@ -245,7 +244,7 @@ func createFontByStripping(newFontFile, fontFile string, runes []rune) error { for _, r := range runes { unicodes = append(unicodes, fmt.Sprintf(`%04X`, r)) } - cmd := execabs.Command( + cmd := exec.Command( "pyftsubset", fontPath(fontFile), "--output-file="+fontPath(newFontFile), From dff4cd7b930015b7f826dc92bf19240dc75dfe46 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:39:59 +0100 Subject: [PATCH 09/22] Fix some crashes for atomic function references --- internal/app/lifecycle.go | 16 ++++++++-------- widget/bind_helper.go | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/app/lifecycle.go b/internal/app/lifecycle.go index 71c826d93a..169bdcb9f6 100644 --- a/internal/app/lifecycle.go +++ b/internal/app/lifecycle.go @@ -50,40 +50,40 @@ func (l *Lifecycle) SetOnStopped(f func()) { // TriggerEnteredForeground will call the focus gained hook, if one is registered. func (l *Lifecycle) TriggerEnteredForeground() { - f := *l.onForeground.Load() + f := l.onForeground.Load() if f == nil { return } - f() + (*f)() } // TriggerExitedForeground will call the focus lost hook, if one is registered. func (l *Lifecycle) TriggerExitedForeground() { - f := *l.onBackground.Load() + f := l.onBackground.Load() if f == nil { return } - f() + (*f)() } // TriggerStarted will call the started hook, if one is registered. func (l *Lifecycle) TriggerStarted() { - f := *l.onStarted.Load() + f := l.onStarted.Load() if f == nil { return } - f() + (*f)() } // TriggerStopped will call the stopped hook, if one is registered, // and an internal stopped hook after that. func (l *Lifecycle) TriggerStopped() { - f := *l.onStopped.Load() + f := l.onStopped.Load() if f != nil { - f() + (*f)() } if l.onStoppedHookExecuted != nil { diff --git a/widget/bind_helper.go b/widget/bind_helper.go index 069c5ed0cf..019424b5da 100644 --- a/widget/bind_helper.go +++ b/widget/bind_helper.go @@ -19,12 +19,12 @@ type basicBinder struct { // Bind replaces the data item whose changes are tracked by the callback function. func (binder *basicBinder) Bind(data binding.DataItem) { listener := binding.NewDataListener(func() { // NB: listener captures `data` but always calls the up-to-date callback - f := *binder.callback.Load() + f := binder.callback.Load() if f == nil { return } - f(data) + (*f)(data) }) data.AddListener(listener) listenerInfo := annotatedListener{ From 77fe5c6cfebb16dc571c145994fb318704e24fbb Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 14:14:19 +0100 Subject: [PATCH 10/22] Fix incorrect generation of async queue --- internal/async/queue_pure_canvasobject.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go index 05bd739014..e2f44fc10c 100755 --- a/internal/async/queue_pure_canvasobject.go +++ b/internal/async/queue_pure_canvasobject.go @@ -5,6 +5,8 @@ package async import ( + "sync/atomic" + "fyne.io/fyne/v2" ) From e015a117bac6a3b6e725ebe9a64c943e54a0353f Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 14:34:41 +0100 Subject: [PATCH 11/22] Update uri to v1.1.0 for faster performance --- go.mod | 2 +- go.sum | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index c590cf6416..88d4b1ac6d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 - github.com/fredbi/uri v1.0.0 + github.com/fredbi/uri v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 diff --git a/go.sum b/go.sum index 7041263d55..488bf10414 100644 --- a/go.sum +++ b/go.sum @@ -75,10 +75,11 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fredbi/uri v1.0.0 h1:s4QwUAZ8fz+mbTsukND+4V5f+mJ/wjaTokwstGUAemg= -github.com/fredbi/uri v1.0.0/go.mod h1:1xC40RnIOGCaQzswaOvrzvG/3M3F0hyDVb3aO/1iGy0= +github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= +github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -168,6 +169,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -246,6 +248,7 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -277,7 +280,6 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -285,7 +287,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= From 53eceaeb56c1c2d5932a62c2f0186e700856c0e2 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 14:41:14 +0100 Subject: [PATCH 12/22] Update golang.org/x/image for various improvements --- go.mod | 4 ++-- go.sum | 26 ++++---------------------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 88d4b1ac6d..b920644851 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.4.0 github.com/yuin/goldmark v1.5.5 - golang.org/x/image v0.11.0 + golang.org/x/image v0.14.0 golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda golang.org/x/mod v0.12.0 golang.org/x/sys v0.13.0 @@ -46,7 +46,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tevino/abool v1.2.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect ) diff --git a/go.sum b/go.sum index 488bf10414..df68a95768 100644 --- a/go.sum +++ b/go.sum @@ -300,7 +300,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.5 h1:IJznPe8wOzfIKETmMkd06F8nXkmlhaHqFRM9l1hAGsU= github.com/yuin/goldmark v1.5.5/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -324,7 +323,6 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -338,8 +336,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= -golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= +golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= +golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -366,8 +364,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -407,8 +403,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -434,8 +428,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -483,15 +475,10 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -500,11 +487,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -561,8 +545,6 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From f68f986f2de7f7efd592c440827f1931ebc473e1 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 15:03:12 +0100 Subject: [PATCH 13/22] Update other golang.org/x deps for Go 1.18 base --- go.mod | 10 +++++----- go.sum | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index b920644851..4f60e2a5e1 100644 --- a/go.mod +++ b/go.mod @@ -29,10 +29,10 @@ require ( github.com/urfave/cli/v2 v2.4.0 github.com/yuin/goldmark v1.5.5 golang.org/x/image v0.14.0 - golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda - golang.org/x/mod v0.12.0 - golang.org/x/sys v0.13.0 - golang.org/x/tools v0.12.0 + golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a + golang.org/x/mod v0.14.0 + golang.org/x/sys v0.15.0 + golang.org/x/tools v0.16.1 ) require ( @@ -45,7 +45,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tevino/abool v1.2.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect diff --git a/go.sum b/go.sum index df68a95768..925005bb9b 100644 --- a/go.sum +++ b/go.sum @@ -353,8 +353,8 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= -golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda h1:O+EUvnBNPwI4eLthn8W5K+cS8zQZfgTABPLNm6Bna34= -golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY= +golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a h1:sYbmY3FwUWCBTodZL1S3JUuOvaW6kM2o+clDzzDNBWg= +golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a/go.mod h1:Ede7gF0KGoHlj822RtphAHK1jLdrcuRBZg0sF1Q+SPc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -364,8 +364,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -403,8 +403,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -428,7 +428,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -476,8 +476,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -545,8 +545,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 50a1ab42a926bdc867b4251415771776cd1b3581 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 16:47:26 +0100 Subject: [PATCH 14/22] Rework async queue to not use unsafe --- internal/async/gen.go | 127 -------------------- internal/async/queue_canvasobject.go | 55 ++++++--- internal/async/queue_pure_canvasobject.go | 43 ------- internal/async/queue_unsafe_canvasobject.go | 41 ------- 4 files changed, 39 insertions(+), 227 deletions(-) delete mode 100755 internal/async/queue_pure_canvasobject.go delete mode 100755 internal/async/queue_unsafe_canvasobject.go diff --git a/internal/async/gen.go b/internal/async/gen.go index b31a3a68a9..2ff74fa252 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -45,29 +45,6 @@ func main() { Imports: "", }, }, - queueImpl: { - "queue_canvasobject.go": { - Type: "fyne.CanvasObject", - Name: "CanvasObject", - Imports: `import ( - "sync" - - "fyne.io/fyne/v2" - )`, - }, - }, - queueUnsafeStructImpl: { - "queue_unsafe_canvasobject.go": { - Type: "fyne.CanvasObject", - Name: "CanvasObject", - Imports: `import ( - "sync/atomic" - "unsafe" - - "fyne.io/fyne/v2" - )`, - }, - }, } for tmpl, types := range codes { @@ -190,107 +167,3 @@ func (ch *Unbounded{{.Name}}Chan) closed() { close(ch.close) } `)) - -var queueUnsafeStructImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. - -package async - -{{.Imports}} - -// {{.Name}}Queue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type {{.Name}}Queue struct { - head unsafe.Pointer - tail unsafe.Pointer - len atomic.Uint64 -} - -// New{{.Name}}Queue returns a queue for caching values. -func New{{.Name}}Queue() *{{.Name}}Queue { - head := &item{{.Name}}{next: nil, v: nil} - return &{{.Name}}Queue{ - tail: unsafe.Pointer(head), - head: unsafe.Pointer(head), - } -} - -type item{{.Name}} struct { - next unsafe.Pointer - v {{.Type}} -} - -func load{{.Name}}Item(p *unsafe.Pointer) *item{{.Name}} { - return (*item{{.Name}})(atomic.LoadPointer(p)) -} - -func cas{{.Name}}Item(p *unsafe.Pointer, old, new *item{{.Name}}) bool { - return atomic.CompareAndSwapPointer(p, unsafe.Pointer(old), unsafe.Pointer(new)) -} -`)) - -var queueImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. - -package async - -{{.Imports}} - -var item{{.Name}}Pool = sync.Pool{ - New: func() interface{} { return &item{{.Name}}{next: nil, v: nil} }, -} - -// In puts the given value at the tail of the queue. -func (q *{{.Name}}Queue) In(v {{.Type}}) { - i := item{{.Name}}Pool.Get().(*item{{.Name}}) - i.next = nil - i.v = v - - var last, lastnext *item{{.Name}} - for { - last = load{{.Name}}Item(&q.tail) - lastnext = load{{.Name}}Item(&last.next) - if load{{.Name}}Item(&q.tail) == last { - if lastnext == nil { - if cas{{.Name}}Item(&last.next, lastnext, i) { - cas{{.Name}}Item(&q.tail, last, i) - q.len.Add(1) - return - } - } else { - cas{{.Name}}Item(&q.tail, last, lastnext) - } - } - } -} - -// Out removes and returns the value at the head of the queue. -// It returns nil if the queue is empty. -func (q *{{.Name}}Queue) Out() {{.Type}} { - var first, last, firstnext *item{{.Name}} - for { - first = load{{.Name}}Item(&q.head) - last = load{{.Name}}Item(&q.tail) - firstnext = load{{.Name}}Item(&first.next) - if first == load{{.Name}}Item(&q.head) { - if first == last { - if firstnext == nil { - return nil - } - cas{{.Name}}Item(&q.tail, last, firstnext) - } else { - v := firstnext.v - if cas{{.Name}}Item(&q.head, first, firstnext) { - q.len.Add(^uint64(0)) - item{{.Name}}Pool.Put(first) - return v - } - } - } - } -} - -// Len returns the length of the queue. -func (q *{{.Name}}Queue) Len() uint64 { - return q.len.Load() -} -`)) diff --git a/internal/async/queue_canvasobject.go b/internal/async/queue_canvasobject.go index 1af42f28df..5ccd42bf6e 100755 --- a/internal/async/queue_canvasobject.go +++ b/internal/async/queue_canvasobject.go @@ -1,36 +1,58 @@ -// Code generated by go run gen.go; DO NOT EDIT. - package async import ( "sync" + "sync/atomic" "fyne.io/fyne/v2" ) +// CanvasObjectQueue implements lock-free FIFO freelist based queue. +// +// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 +type CanvasObjectQueue struct { + head atomic.Pointer[itemCanvasObject] + tail atomic.Pointer[itemCanvasObject] + len atomic.Uint64 +} + +// NewCanvasObjectQueue returns a queue for caching values. +func NewCanvasObjectQueue() *CanvasObjectQueue { + head := &itemCanvasObject{} + queue := &CanvasObjectQueue{} + queue.head.Store(head) + queue.tail.Store(head) + return queue +} + +type itemCanvasObject struct { + next atomic.Pointer[itemCanvasObject] + v fyne.CanvasObject +} + var itemCanvasObjectPool = sync.Pool{ - New: func() interface{} { return &itemCanvasObject{next: nil, v: nil} }, + New: func() interface{} { return &itemCanvasObject{} }, } // In puts the given value at the tail of the queue. func (q *CanvasObjectQueue) In(v fyne.CanvasObject) { i := itemCanvasObjectPool.Get().(*itemCanvasObject) - i.next = nil + i.next.Store(nil) i.v = v var last, lastnext *itemCanvasObject for { - last = loadCanvasObjectItem(&q.tail) - lastnext = loadCanvasObjectItem(&last.next) - if loadCanvasObjectItem(&q.tail) == last { + last = q.tail.Load() + lastnext = last.next.Load() + if q.tail.Load() == last { if lastnext == nil { - if casCanvasObjectItem(&last.next, lastnext, i) { - casCanvasObjectItem(&q.tail, last, i) + if last.next.CompareAndSwap(lastnext, i) { + q.tail.CompareAndSwap(last, i) q.len.Add(1) return } } else { - casCanvasObjectItem(&q.tail, last, lastnext) + q.tail.CompareAndSwap(last, lastnext) } } } @@ -41,18 +63,19 @@ func (q *CanvasObjectQueue) In(v fyne.CanvasObject) { func (q *CanvasObjectQueue) Out() fyne.CanvasObject { var first, last, firstnext *itemCanvasObject for { - first = loadCanvasObjectItem(&q.head) - last = loadCanvasObjectItem(&q.tail) - firstnext = loadCanvasObjectItem(&first.next) - if first == loadCanvasObjectItem(&q.head) { + first = q.head.Load() + last = q.tail.Load() + firstnext = first.next.Load() + if first == q.head.Load() { if first == last { if firstnext == nil { return nil } - casCanvasObjectItem(&q.tail, last, firstnext) + + q.tail.CompareAndSwap(last, firstnext) } else { v := firstnext.v - if casCanvasObjectItem(&q.head, first, firstnext) { + if q.head.CompareAndSwap(first, firstnext) { q.len.Add(^uint64(0)) itemCanvasObjectPool.Put(first) return v diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go deleted file mode 100755 index e2f44fc10c..0000000000 --- a/internal/async/queue_pure_canvasobject.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by go run gen.go; DO NOT EDIT. -//go:build js -// +build js - -package async - -import ( - "sync/atomic" - - "fyne.io/fyne/v2" -) - -// CanvasObjectQueue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type CanvasObjectQueue struct { - head *itemCanvasObject - tail *itemCanvasObject - len atomic.Uint64 -} - -// NewCanvasObjectQueue returns a queue for caching values. -func NewCanvasObjectQueue() *CanvasObjectQueue { - head := &itemCanvasObject{next: nil, v: nil} - return &CanvasObjectQueue{ - tail: head, - head: head, - } -} - -type itemCanvasObject struct { - next *itemCanvasObject - v fyne.CanvasObject -} - -func loadCanvasObjectItem(p **itemCanvasObject) *itemCanvasObject { - return *p -} - -func casCanvasObjectItem(p **itemCanvasObject, _, new *itemCanvasObject) bool { - *p = new - return true -} diff --git a/internal/async/queue_unsafe_canvasobject.go b/internal/async/queue_unsafe_canvasobject.go deleted file mode 100755 index 5fbb99d26a..0000000000 --- a/internal/async/queue_unsafe_canvasobject.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by go run gen.go; DO NOT EDIT. - -package async - -import ( - "sync/atomic" - "unsafe" - - "fyne.io/fyne/v2" -) - -// CanvasObjectQueue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type CanvasObjectQueue struct { - head unsafe.Pointer - tail unsafe.Pointer - len atomic.Uint64 -} - -// NewCanvasObjectQueue returns a queue for caching values. -func NewCanvasObjectQueue() *CanvasObjectQueue { - head := &itemCanvasObject{next: nil, v: nil} - return &CanvasObjectQueue{ - tail: unsafe.Pointer(head), - head: unsafe.Pointer(head), - } -} - -type itemCanvasObject struct { - next unsafe.Pointer - v fyne.CanvasObject -} - -func loadCanvasObjectItem(p *unsafe.Pointer) *itemCanvasObject { - return (*itemCanvasObject)(atomic.LoadPointer(p)) -} - -func casCanvasObjectItem(p *unsafe.Pointer, old, new *itemCanvasObject) bool { - return atomic.CompareAndSwapPointer(p, unsafe.Pointer(old), unsafe.Pointer(new)) -} From c8bbbfd1326ac4bd91a17374781b32d1ada38172 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 16:59:56 +0100 Subject: [PATCH 15/22] More atomic.Value cleanups --- app.go | 15 +++------------ internal/cache/base.go | 9 +++++---- internal/cache/text.go | 4 ++-- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app.go b/app.go index bffcf9c1ff..74ac0bf89a 100644 --- a/app.go +++ b/app.go @@ -81,20 +81,11 @@ type App interface { SetCloudProvider(CloudProvider) // configure cloud for this app } -// app contains an App variable, but due to atomic.Value restrictions on -// interfaces we need to use an indirect type, i.e. appContainer. -var app atomic.Pointer[appContainer] // appContainer - -// appContainer is a dummy container that holds an App instance. This -// struct exists to guarantee that atomic.Value can store objects with -// same type. -type appContainer struct { - current App -} +var app atomic.Pointer[App] // SetCurrentApp is an internal function to set the app instance currently running. func SetCurrentApp(current App) { - app.Store(&appContainer{current}) + app.Store(¤t) } // CurrentApp returns the current application, for which there is only 1 per process. @@ -104,7 +95,7 @@ func CurrentApp() App { LogError("Attempt to access current Fyne app when none is started", nil) return nil } - return val.current + return *val } // AppMetadata captures the build metadata for an application. diff --git a/internal/cache/base.go b/internal/cache/base.go index 204e8f4604..92b0167e11 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -155,7 +155,7 @@ func ResetThemeCaches() { }) fontSizeLock.Lock() - fontSizeCache = map[fontSizeEntry]fontMetric{} + fontSizeCache = map[fontSizeEntry]*fontMetric{} fontSizeLock.Unlock() } @@ -215,7 +215,7 @@ func matchesACanvas(cinfo *canvasInfo, canvases []fyne.Canvas) bool { } type expiringCache struct { - expires atomic.Value // time.time + expires atomic.Pointer[time.Time] } // isExpired check if the cache data is expired. @@ -224,12 +224,13 @@ func (c *expiringCache) isExpired(now time.Time) bool { if t == nil { return (time.Time{}).Before(now) } - return t.(time.Time).Before(now) + return (*t).Before(now) } // setAlive updates expiration time. func (c *expiringCache) setAlive() { - c.expires.Store(timeNow().Add(cacheDuration)) + time := timeNow().Add(cacheDuration) + c.expires.Store(&time) } type expiringCacheNoLock struct { diff --git a/internal/cache/text.go b/internal/cache/text.go index 13ab450577..465caec5bf 100644 --- a/internal/cache/text.go +++ b/internal/cache/text.go @@ -8,7 +8,7 @@ import ( ) var ( - fontSizeCache = map[fontSizeEntry]fontMetric{} + fontSizeCache = map[fontSizeEntry]*fontMetric{} fontSizeLock = sync.RWMutex{} ) @@ -40,7 +40,7 @@ func GetFontMetrics(text string, fontSize float32, style fyne.TextStyle) (size f // SetFontMetrics stores a calculated font size and baseline for parameters that were missing from the cache. func SetFontMetrics(text string, fontSize float32, style fyne.TextStyle, size fyne.Size, base float32) { ent := fontSizeEntry{text, fontSize, style} - metric := fontMetric{size: size, baseLine: base} + metric := &fontMetric{size: size, baseLine: base} metric.setAlive() fontSizeLock.Lock() fontSizeCache[ent] = metric From 325103a98fb3ae8f46bbf7eb726c1fc347dec31e Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 17:04:39 +0100 Subject: [PATCH 16/22] Use atomic.Pointer for preference bindings --- data/binding/gen.go | 11 ++++------ data/binding/preference.go | 44 ++++++++++++++------------------------ 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/data/binding/gen.go b/data/binding/gen.go index 6b444a8ad6..ec6afd3868 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -122,7 +122,7 @@ type prefBound{{ .Name }} struct { base key string p fyne.Preferences - cache atomic.Value // {{ .Type }} + cache atomic.Pointer[{{ .Type }}] } // BindPreference{{ .Name }} returns a bindable {{ .Type }} value that is managed by the application preferences. @@ -148,7 +148,7 @@ func BindPreference{{ .Name }}(key string, p fyne.Preferences) {{ .Name }} { func (b *prefBound{{ .Name }}) Get() ({{ .Type }}, error) { cache := b.p.{{ .Name }}(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -163,11 +163,8 @@ func (b *prefBound{{ .Name }}) Set(v {{ .Type }}) error { func (b *prefBound{{ .Name }}) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.({{ .Type }}) - if b.p.{{ .Name }}(b.key) == cache { - return - } + if val != nil && b.p.{{ .Name }}(b.key) == *val { + return } b.trigger() } diff --git a/data/binding/preference.go b/data/binding/preference.go index 27dc3d9448..81b0b7c1be 100644 --- a/data/binding/preference.go +++ b/data/binding/preference.go @@ -15,7 +15,7 @@ type prefBoundBool struct { base key string p fyne.Preferences - cache atomic.Value // bool + cache atomic.Pointer[bool] } // BindPreferenceBool returns a bindable bool value that is managed by the application preferences. @@ -41,7 +41,7 @@ func BindPreferenceBool(key string, p fyne.Preferences) Bool { func (b *prefBoundBool) Get() (bool, error) { cache := b.p.Bool(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -56,11 +56,8 @@ func (b *prefBoundBool) Set(v bool) error { func (b *prefBoundBool) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(bool) - if b.p.Bool(b.key) == cache { - return - } + if val != nil && b.p.Bool(b.key) == *val { + return } b.trigger() } @@ -73,7 +70,7 @@ type prefBoundFloat struct { base key string p fyne.Preferences - cache atomic.Value // float64 + cache atomic.Pointer[float64] } // BindPreferenceFloat returns a bindable float64 value that is managed by the application preferences. @@ -99,7 +96,7 @@ func BindPreferenceFloat(key string, p fyne.Preferences) Float { func (b *prefBoundFloat) Get() (float64, error) { cache := b.p.Float(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -114,11 +111,8 @@ func (b *prefBoundFloat) Set(v float64) error { func (b *prefBoundFloat) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(float64) - if b.p.Float(b.key) == cache { - return - } + if val != nil && b.p.Float(b.key) == *val { + return } b.trigger() } @@ -131,7 +125,7 @@ type prefBoundInt struct { base key string p fyne.Preferences - cache atomic.Value // int + cache atomic.Pointer[int] } // BindPreferenceInt returns a bindable int value that is managed by the application preferences. @@ -157,7 +151,7 @@ func BindPreferenceInt(key string, p fyne.Preferences) Int { func (b *prefBoundInt) Get() (int, error) { cache := b.p.Int(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -172,11 +166,8 @@ func (b *prefBoundInt) Set(v int) error { func (b *prefBoundInt) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(int) - if b.p.Int(b.key) == cache { - return - } + if val != nil && b.p.Int(b.key) == *val { + return } b.trigger() } @@ -189,7 +180,7 @@ type prefBoundString struct { base key string p fyne.Preferences - cache atomic.Value // string + cache atomic.Pointer[string] } // BindPreferenceString returns a bindable string value that is managed by the application preferences. @@ -215,7 +206,7 @@ func BindPreferenceString(key string, p fyne.Preferences) String { func (b *prefBoundString) Get() (string, error) { cache := b.p.String(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -230,11 +221,8 @@ func (b *prefBoundString) Set(v string) error { func (b *prefBoundString) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(string) - if b.p.String(b.key) == cache { - return - } + if val != nil && b.p.String(b.key) == *val { + return } b.trigger() } From b25a148187564771e7a1e78e6cf0607453c051ad Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:13:31 +0100 Subject: [PATCH 17/22] internal/async: Add a generic unbound channel Requires Go 1.21 for the clear() builtin but will allow us to cut down on generation scripts later on. --- internal/async/chan_canvasobject.go | 4 +- internal/async/chan_func.go | 4 +- internal/async/chan_go1.21.go | 124 ++++++++++++++++++++++++++++ internal/async/chan_interface.go | 4 +- internal/async/gen.go | 2 +- 5 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 internal/async/chan_go1.21.go diff --git a/internal/async/chan_canvasobject.go b/internal/async/chan_canvasobject.go index 69ca5d7afb..7a88a68368 100755 --- a/internal/async/chan_canvasobject.go +++ b/internal/async/chan_canvasobject.go @@ -1,5 +1,7 @@ -// Code generated by go run gen.go; DO NOT EDIT. +//go:build !go1.21 +// Code generated by go run gen.go; DO NOT EDIT. +// package async import "fyne.io/fyne/v2" diff --git a/internal/async/chan_func.go b/internal/async/chan_func.go index ccf4ad9b31..5c58619343 100755 --- a/internal/async/chan_func.go +++ b/internal/async/chan_func.go @@ -1,5 +1,7 @@ -// Code generated by go run gen.go; DO NOT EDIT. +//go:build !go1.21 +// Code generated by go run gen.go; DO NOT EDIT. +// package async // UnboundedFuncChan is a channel with an unbounded buffer for caching diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go new file mode 100644 index 0000000000..7353d7caa9 --- /dev/null +++ b/internal/async/chan_go1.21.go @@ -0,0 +1,124 @@ +//go:build go1.21 + +package async + +import "fyne.io/fyne/v2" + +// UnboundedFuncChan is a channel with an unbounded buffer for caching +// Func objects. A channel must be closed via Close method. +type UnboundedChan[T any] struct { + in, out chan T + close chan struct{} + q []T +} + +// NewUnboundedFuncChan returns a unbounded channel with unlimited capacity. +func NewUnboundedChan[T any]() *UnboundedChan[T] { + ch := &UnboundedChan[T]{ + // The size of Func is less than 16 bytes, we use 16 to fit + // a CPU cache line (L2, 256 Bytes), which may reduce cache misses. + in: make(chan T, 16), + out: make(chan T, 16), + close: make(chan struct{}), + } + go ch.processing() + return ch +} + +// In returns the send channel of the given channel, which can be used to +// send values to the channel. +func (ch *UnboundedChan[T]) In() chan<- T { return ch.in } + +// Out returns the receive channel of the given channel, which can be used +// to receive values from the channel. +func (ch *UnboundedChan[T]) Out() <-chan T { return ch.out } + +// Close closes the channel. +func (ch *UnboundedChan[T]) Close() { ch.close <- struct{}{} } + +func (ch *UnboundedChan[T]) processing() { + // This is a preallocation of the internal unbounded buffer. + // The size is randomly picked. But if one changes the size, the + // reallocation size at the subsequent for loop should also be + // changed too. Furthermore, there is no memory leak since the + // queue is garbage collected. + ch.q = make([]T, 0, 1<<10) + for { + select { + case e, ok := <-ch.in: + if !ok { + // We don't want the input channel be accidentally closed + // via close() instead of Close(). If that happens, it is + // a misuse, do a panic as warning. + panic("async: misuse of unbounded channel, In() was closed") + } + ch.q = append(ch.q, e) + case <-ch.close: + ch.closed() + return + } + for len(ch.q) > 0 { + select { + case ch.out <- ch.q[0]: + clear(ch.q[:1]) // de-reference earlier to help GC + ch.q = ch.q[1:] + case e, ok := <-ch.in: + if !ok { + // We don't want the input channel be accidentally closed + // via close() instead of Close(). If that happens, it is + // a misuse, do a panic as warning. + panic("async: misuse of unbounded channel, In() was closed") + } + ch.q = append(ch.q, e) + case <-ch.close: + ch.closed() + return + } + } + // If the remaining capacity is too small, we prefer to + // reallocate the entire buffer. + if cap(ch.q) < 1<<5 { + ch.q = make([]T, 0, 1<<10) + } + } +} + +func (ch *UnboundedChan[T]) closed() { + close(ch.in) + for e := range ch.in { + ch.q = append(ch.q, e) + } + for len(ch.q) > 0 { + select { + case ch.out <- ch.q[0]: + clear(ch.q[:1]) // de-reference earlier to help GC + ch.q = ch.q[1:] + default: + } + } + close(ch.out) + close(ch.close) +} + +// UnboundedFuncChan is a channel with an unbounded buffer for caching +// Func objects. A channel must be closed via Close method +type UnboundedFuncChan = UnboundedChan[func()] + +// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. +func NewUnboundedFuncChan() *UnboundedChan[func()] { + return NewUnboundedChan[func()]() +} + +// UnboundedInterfaceChan is a channel with an unbounded buffer for caching +// Interface objects. A channel must be closed via Close method. +type UnboundedInterfaceChan = UnboundedChan[any] + +// NewUnboundedInterfaceChan returns a unbounded channel, of any type, with unlimited capacity. +func NewUnboundedInterfaceChan() *UnboundedChan[any] { + return NewUnboundedChan[any]() +} + +// NewUnboundedCanvasObjectChan returns a unbounded channel, of canvas objects, with unlimited capacity. +func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { + return NewUnboundedChan[fyne.CanvasObject]() +} diff --git a/internal/async/chan_interface.go b/internal/async/chan_interface.go index 9c39f6f605..ec7533c0d2 100755 --- a/internal/async/chan_interface.go +++ b/internal/async/chan_interface.go @@ -1,5 +1,7 @@ -// Code generated by go run gen.go; DO NOT EDIT. +//go:build !go1.21 +// Code generated by go run gen.go; DO NOT EDIT. +// package async // UnboundedInterfaceChan is a channel with an unbounded buffer for caching diff --git a/internal/async/gen.go b/internal/async/gen.go index 2ff74fa252..c52b265a0c 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -66,7 +66,7 @@ func main() { } var chanImpl = template.Must(template.New("async").Parse(`// Code generated by go run gen.go; DO NOT EDIT. - +//go:build !go1.21 package async {{.Imports}} From 317df119fd38828f514d94e8d6fe140bbf8f0d94 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:22:35 +0100 Subject: [PATCH 18/22] Reorder fields to the top --- internal/async/chan_go1.21.go | 50 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go index 7353d7caa9..d04bb7e3af 100644 --- a/internal/async/chan_go1.21.go +++ b/internal/async/chan_go1.21.go @@ -4,6 +4,33 @@ package async import "fyne.io/fyne/v2" +// UnboundedFuncChan is a channel with an unbounded buffer for caching +// Func objects. A channel must be closed via Close method +type UnboundedFuncChan = UnboundedChan[func()] + +// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. +func NewUnboundedFuncChan() *UnboundedFuncChan { + return NewUnboundedChan[func()]() +} + +// UnboundedInterfaceChan is a channel with an unbounded buffer for caching +// Interface objects. A channel must be closed via Close method. +type UnboundedInterfaceChan = UnboundedChan[any] + +// NewUnboundedInterfaceChan returns a unbounded channel, of any type, with unlimited capacity. +func NewUnboundedInterfaceChan() *UnboundedInterfaceChan { + return NewUnboundedChan[any]() +} + +// UnboundedCanvasObjectChan is a channel with an unbounded buffer for caching +// CanvasObject objects. A channel must be closed via Close method. +type UnboundedCanvasObjectChan = UnboundedChan[fyne.CanvasObject] + +// NewUnboundedCanvasObjectChan returns a unbounded channel, of canvas objects, with unlimited capacity. +func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { + return NewUnboundedChan[fyne.CanvasObject]() +} + // UnboundedFuncChan is a channel with an unbounded buffer for caching // Func objects. A channel must be closed via Close method. type UnboundedChan[T any] struct { @@ -99,26 +126,3 @@ func (ch *UnboundedChan[T]) closed() { close(ch.out) close(ch.close) } - -// UnboundedFuncChan is a channel with an unbounded buffer for caching -// Func objects. A channel must be closed via Close method -type UnboundedFuncChan = UnboundedChan[func()] - -// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. -func NewUnboundedFuncChan() *UnboundedChan[func()] { - return NewUnboundedChan[func()]() -} - -// UnboundedInterfaceChan is a channel with an unbounded buffer for caching -// Interface objects. A channel must be closed via Close method. -type UnboundedInterfaceChan = UnboundedChan[any] - -// NewUnboundedInterfaceChan returns a unbounded channel, of any type, with unlimited capacity. -func NewUnboundedInterfaceChan() *UnboundedChan[any] { - return NewUnboundedChan[any]() -} - -// NewUnboundedCanvasObjectChan returns a unbounded channel, of canvas objects, with unlimited capacity. -func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { - return NewUnboundedChan[fyne.CanvasObject]() -} From 89db36b298106598a0a69b6a7252810a360a75ae Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:29:45 +0100 Subject: [PATCH 19/22] Update an out of date comment --- internal/async/chan_go1.21.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go index d04bb7e3af..7b0407c94e 100644 --- a/internal/async/chan_go1.21.go +++ b/internal/async/chan_go1.21.go @@ -42,7 +42,7 @@ type UnboundedChan[T any] struct { // NewUnboundedFuncChan returns a unbounded channel with unlimited capacity. func NewUnboundedChan[T any]() *UnboundedChan[T] { ch := &UnboundedChan[T]{ - // The size of Func is less than 16 bytes, we use 16 to fit + // The size of Func, Interface, and CanvasObject are all less than 16 bytes, we use 16 to fit // a CPU cache line (L2, 256 Bytes), which may reduce cache misses. in: make(chan T, 16), out: make(chan T, 16), From 74ae818080f734cf76e40796c02ffc7801b5606b Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:38:48 +0100 Subject: [PATCH 20/22] Make goimports happier --- internal/async/chan_canvasobject.go | 1 - internal/async/chan_func.go | 1 - internal/async/chan_interface.go | 1 - internal/async/gen.go | 5 +++-- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/async/chan_canvasobject.go b/internal/async/chan_canvasobject.go index 7a88a68368..6af88ba323 100755 --- a/internal/async/chan_canvasobject.go +++ b/internal/async/chan_canvasobject.go @@ -1,7 +1,6 @@ //go:build !go1.21 // Code generated by go run gen.go; DO NOT EDIT. -// package async import "fyne.io/fyne/v2" diff --git a/internal/async/chan_func.go b/internal/async/chan_func.go index 5c58619343..26e2e926f9 100755 --- a/internal/async/chan_func.go +++ b/internal/async/chan_func.go @@ -1,7 +1,6 @@ //go:build !go1.21 // Code generated by go run gen.go; DO NOT EDIT. -// package async // UnboundedFuncChan is a channel with an unbounded buffer for caching diff --git a/internal/async/chan_interface.go b/internal/async/chan_interface.go index ec7533c0d2..89e065ce5c 100755 --- a/internal/async/chan_interface.go +++ b/internal/async/chan_interface.go @@ -1,7 +1,6 @@ //go:build !go1.21 // Code generated by go run gen.go; DO NOT EDIT. -// package async // UnboundedInterfaceChan is a channel with an unbounded buffer for caching diff --git a/internal/async/gen.go b/internal/async/gen.go index c52b265a0c..846ff3f9a9 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -65,8 +65,9 @@ func main() { } } -var chanImpl = template.Must(template.New("async").Parse(`// Code generated by go run gen.go; DO NOT EDIT. -//go:build !go1.21 +var chanImpl = template.Must(template.New("async").Parse(`//go:build !go1.21 + +// Code generated by go run gen.go; DO NOT EDIT. package async {{.Imports}} From 049f4e410b98f9c81b59ac5ba921041dc381b02e Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 21:55:41 +0100 Subject: [PATCH 21/22] Update systray to Go 1.19 version --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4f60e2a5e1..3ae5699b13 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module fyne.io/fyne/v2 go 1.19 require ( - fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e + fyne.io/systray v1.10.1-0.20231230205326-d160fd363db9 github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 github.com/fredbi/uri v1.1.0 @@ -44,7 +44,6 @@ require ( github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/tevino/abool v1.2.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 925005bb9b..13bbed2896 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e h1:Hvs+kW2VwCzNToF3FmnIAzmivNgrclwPgoUdVSrjkP8= -fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e/go.mod h1:oM2AQqGJ1AMo4nNqZFYU8xYygSBZkW2hmdJ7n4yjedE= +fyne.io/systray v1.10.1-0.20231230205326-d160fd363db9 h1:E/gHmMVyk8TuI6JIgNIv/Qu1JABMVFBIkQ8lYRa5gkQ= +fyne.io/systray v1.10.1-0.20231230205326-d160fd363db9/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -290,8 +290,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA= -github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg= github.com/urfave/cli/v2 v2.4.0 h1:m2pxjjDFgDxSPtO8WSdbndj17Wu2y8vOT86wE/tjr+I= github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From 081664a96fe236fa09f2943366f96ba775069a2f Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 2 Jan 2024 11:46:17 +0100 Subject: [PATCH 22/22] Update to glfw-js without GopherJS support --- go.mod | 3 +-- go.sum | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 3ae5699b13..e93f68042d 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/fredbi/uri v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe - github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 + github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 @@ -47,5 +47,4 @@ require ( golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect ) diff --git a/go.sum b/go.sum index 13bbed2896..70e172995a 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJytaD+SsXkPU0asQ+guQEIg1BJGX4= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg= -github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 h1:0Ayg0/do/sqX2R7NonoLZvWxGrd9utTVf3A0QvCbC88= -github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= +github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a h1:ybgRdYvAHTn93HW79bLiBiJwVL4jVeyGQRZMgImoeWs= +github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a/go.mod h1:gsGA2dotD4v0SR6PmPCYvS9JuOeMwAtmfvDE7mbYXMY= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 h1:hnLq+55b7Zh7/2IRzWCpiTcAvjv/P8ERF+N7+xXbZhk= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2/go.mod h1:eO7W361vmlPOrykIg+Rsh1SZ3tQBaOsfzZhsIOb/Lm0= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -95,7 +95,6 @@ github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVin github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 h1:7tf/0aw5DxRQjr7WaNqgtjidub6v21L2cogKIbMcTYw= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -179,7 +178,6 @@ github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60/go.mod h1:cz9oNY github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/goxjs/gl v0.0.0-20210104184919-e3fafc6f8f2a/go.mod h1:dy/f2gjY09hwVfIyATps4G2ai7/hLwLkc5TrPqONuXY= -github.com/goxjs/glfw v0.0.0-20191126052801-d2efb5f20838/go.mod h1:oS8P8gVOT4ywTcjV6wZlOU4GuVFQ8F5328KY3MJ79CY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -664,8 +662,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 h1:oomkgU6VaQDsV6qZby2uz1Lap0eXmku8+2em3A/l700= -honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2/go.mod h1:sUMDUKNB2ZcVjt92UnLy3cdGs+wDAcrPdV3JP6sVgA4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=