Restructure event loop to only poll screen between updates

Relates to #58.
This commit is contained in:
Trevor Slocum 2021-04-24 23:08:49 -07:00
parent 9dbc4a3a03
commit 1653d59d6b
2 changed files with 34 additions and 32 deletions

View File

@ -1,3 +1,6 @@
v1.5.5 (WIP)
- Restructure event loop to only poll screen between updates
v1.5.4 (2020-04-03)
- Add TextView.GetBufferSize
- Fix strikethrough support

View File

@ -304,7 +304,7 @@ func (a *Application) Run() error {
a.Unlock()
a.draw()
// Separate loop to wait for screen events.
// Separate loop to wait for screen replacement events.
var wg sync.WaitGroup
wg.Add(1)
go func() {
@ -319,14 +319,6 @@ func (a *Application) Run() error {
break
}
// Wait for next event and queue it.
event := screen.PollEvent()
if event != nil {
// Regular event. Queue.
a.QueueEvent(event)
continue
}
// A screen was finalized (event is nil). Wait for a new screen.
screen = <-a.screenReplacement
if screen == nil {
@ -436,32 +428,38 @@ func (a *Application) Run() error {
}
}
// Start event loop.
EventLoop:
semaphore := &sync.Mutex{}
go func() {
for update := range a.updates {
semaphore.Lock()
update()
semaphore.Unlock()
}
}()
// Start screen event loop.
for {
// Handle events before executing updates
select {
case event := <-a.events:
if event == nil {
break EventLoop
}
handle(event)
continue
default:
a.Lock()
screen := a.screen
a.Unlock()
if screen == nil {
break
}
select {
case event := <-a.events:
if event == nil {
break EventLoop
}
handle(event)
case update := <-a.updates:
update()
// Wait for next event.
event := screen.PollEvent()
if event == nil {
break
}
semaphore.Lock()
handle(event)
semaphore.Unlock()
}
// Wait for the event loop to finish.
// Wait for the screen replacement event loop to finish.
wg.Wait()
a.screen = nil
@ -590,13 +588,12 @@ func (a *Application) Stop() {
// terminal UI mode was not exited, and "f" was not called.
func (a *Application) Suspend(f func()) bool {
a.Lock()
defer a.Unlock()
if a.screen == nil {
a.Unlock()
return false // Screen has not yet been initialized.
}
err := a.screen.Suspend()
a.Unlock()
if err != nil {
panic(err)
}
@ -604,7 +601,9 @@ func (a *Application) Suspend(f func()) bool {
// Wait for "f" to return.
f()
a.Lock()
err = a.screen.Resume()
a.Unlock()
if err != nil {
panic(err)
}