aerc

Working clone of aerc-mail.org
git clone git://git.danielmoch.com/aerc.git
Log | Files | Refs | README | LICENSE

commit 7c6325977b55385bc65f0a08f4da8ed6dfede52a
parent a15ea01cfb0a303355b2e6bb31e85ece0d048ac2
Author: Simon Ser <contact@emersion.fr>
Date:   Sun, 19 May 2019 09:50:14 +0000

lib/ui/ui: use atomic instead of channel

This makes it so an atomic `invalid` value is used instead of an unbuffered
channel. When many invalidations kick in, a lot of values were sent to the
channel.

(Since OnInvalidate's callback can be run in any goroutine, we need to be
careful about races here.)

Diffstat:
Mlib/ui/ui.go | 47+++++++++++++++++++++--------------------------
1 file changed, 21 insertions(+), 26 deletions(-)

diff --git a/lib/ui/ui.go b/lib/ui/ui.go @@ -14,8 +14,8 @@ type UI struct { ctx *Context screen tcell.Screen - tcEvents chan tcell.Event - invalidations chan interface{} + tcEvents chan tcell.Event + invalid int32 // access via atomic } func Initialize(conf *config.AercConfig, @@ -40,24 +40,22 @@ func Initialize(conf *config.AercConfig, ctx: NewContext(width, height, screen), screen: screen, - tcEvents: make(chan tcell.Event, 10), - invalidations: make(chan interface{}), + tcEvents: make(chan tcell.Event, 10), } + state.exit.Store(false) - go (func() { + go func() { for !state.ShouldExit() { state.tcEvents <- screen.PollEvent() } - })() - go (func() { - state.invalidations <- nil - })() + }() + + state.invalid = 1 content.OnInvalidate(func(_ Drawable) { - go (func() { - state.invalidations <- nil - })() + atomic.StoreInt32(&state.invalid, 1) }) content.Focus(true) + return &state, nil } @@ -74,6 +72,8 @@ func (state *UI) Close() { } func (state *UI) Tick() bool { + more := false + select { case event := <-state.tcEvents: switch event := event.(type) { @@ -84,21 +84,16 @@ func (state *UI) Tick() bool { state.Content.Invalidate() } state.Content.Event(event) - case <-state.invalidations: - for { - // Flush any other pending invalidations - select { - case <-state.invalidations: - break - default: - goto done - } - } - done: + more = true + default: + } + + wasInvalid := atomic.SwapInt32(&state.invalid, 0) + if wasInvalid != 0 { state.Content.Draw(state.ctx) state.screen.Show() - default: - return false + more = true } - return true + + return more }