diff options
author | Simon Ser <contact@emersion.fr> | 2019-05-19 09:50:14 +0000 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-05-19 11:51:18 -0400 |
commit | 7c6325977b55385bc65f0a08f4da8ed6dfede52a (patch) | |
tree | 0aac968a8ade4204e57463ec68de7048eaf04668 | |
parent | a15ea01cfb0a303355b2e6bb31e85ece0d048ac2 (diff) | |
download | aerc-7c6325977b55385bc65f0a08f4da8ed6dfede52a.tar.gz |
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.)
-rw-r--r-- | lib/ui/ui.go | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/lib/ui/ui.go b/lib/ui/ui.go index 91a26da..f04d3d8 100644 --- 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 } |