Skip to content

Commit

Permalink
Remove the lock from internal basewidget
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacalz committed Jan 3, 2024
1 parent 910eea1 commit 1dd907c
Showing 1 changed file with 17 additions and 37 deletions.
54 changes: 17 additions & 37 deletions internal/widget/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package widget

import (
"math"
"sync"
"sync/atomic"

"fyne.io/fyne/v2"
Expand All @@ -12,12 +11,10 @@ import (

// Base provides a helper that handles basic widget behaviours.
type Base struct {
hidden bool
hidden atomic.Bool
position atomic.Uint64
size atomic.Uint64

impl fyne.Widget
propertyLock sync.RWMutex
impl atomic.Pointer[fyne.Widget]
}

// ExtendBaseWidget is used by an extending widget to make use of BaseWidget functionality.
Expand All @@ -27,9 +24,7 @@ func (w *Base) ExtendBaseWidget(wid fyne.Widget) {
return
}

w.propertyLock.Lock()
defer w.propertyLock.Unlock()
w.impl = wid
w.impl.Store(&wid)
}

// Size gets the current size of this widget.
Expand Down Expand Up @@ -81,10 +76,7 @@ func (w *Base) MinSize() fyne.Size {
// Visible returns whether or not this widget should be visible.
// Note that this may not mean it is currently visible if a parent has been hidden.
func (w *Base) Visible() bool {
w.propertyLock.RLock()
defer w.propertyLock.RUnlock()

return !w.hidden
return !w.hidden.Load()
}

// Show this widget so it becomes visible
Expand All @@ -93,9 +85,11 @@ func (w *Base) Show() {
return
}

w.setFieldsAndRefresh(func() {
w.hidden = false
})
impl := w.super()
if impl == nil {
return
}
impl.Refresh()
}

// Hide this widget so it is no longer visible
Expand All @@ -104,11 +98,9 @@ func (w *Base) Hide() {
return
}

w.propertyLock.Lock()
w.hidden = true
impl := w.impl
w.propertyLock.Unlock()
w.hidden.Store(true)

impl := w.super()
if impl == nil {
return
}
Expand All @@ -126,27 +118,15 @@ func (w *Base) Refresh() {
render.Refresh()
}

// setFieldsAndRefresh helps to make changes to a widget that should be followed by a refresh.
// This method is a guaranteed thread-safe way of directly manipulating widget fields.
func (w *Base) setFieldsAndRefresh(f func()) {
w.propertyLock.Lock()
f()
impl := w.impl
w.propertyLock.Unlock()

if impl == nil {
return
}
impl.Refresh()
}

// super will return the actual object that this represents.
// If extended then this is the extending widget, otherwise it is nil.
func (w *Base) super() fyne.Widget {
w.propertyLock.RLock()
impl := w.impl
w.propertyLock.RUnlock()
return impl
impl := w.impl.Load()
if impl == nil {
return nil
}

return *impl
}

// Repaint instructs the containing canvas to redraw, even if nothing changed.
Expand Down

0 comments on commit 1dd907c

Please sign in to comment.