11package tview
22
33import (
4+ "context"
45 "strings"
56 "sync"
67 "time"
@@ -478,7 +479,7 @@ EventLoop:
478479 case update := <- a .updates :
479480 update .f ()
480481 if update .done != nil {
481- update .done <- struct {}{}
482+ close ( update .done )
482483 }
483484 }
484485 }
@@ -843,12 +844,40 @@ func (a *Application) GetFocus() Primitive {
843844//
844845// This function returns after f has executed.
845846func (a * Application ) QueueUpdate (f func ()) * Application {
846- ch := make (chan struct {})
847- a .updates <- queuedUpdate {f : f , done : ch }
848- <- ch
847+ _ = a .QueueUpdateContext (context .Background (), f )
848+
849849 return a
850850}
851851
852+ // QueueUpdateContext is used to synchronize access to primitives from non-main
853+ // goroutines. The provided function will be executed as part of the event loop
854+ // and thus will not cause race conditions with other such update functions or
855+ // the Draw() function.
856+ //
857+ // Note that Draw() is not implicitly called after the execution of f as that
858+ // may not be desirable. You can call Draw() from f if the screen should be
859+ // refreshed after each update. Alternatively, use QueueUpdateDraw() to follow
860+ // up with an immediate refresh of the screen.
861+ //
862+ // This function returns with nil after f has executed or with an error
863+ // if context is done before that.
864+ func (a * Application ) QueueUpdateContext (ctx context.Context , f func ()) error {
865+ ch := make (chan struct {})
866+ select {
867+ case <- ctx .Done ():
868+ return ctx .Err ()
869+ case a .updates <- queuedUpdate {f : f , done : ch }:
870+ }
871+
872+ select {
873+ case <- ctx .Done ():
874+ return ctx .Err ()
875+ case <- ch :
876+ }
877+
878+ return nil
879+ }
880+
852881// QueueUpdateDraw works like QueueUpdate() except it refreshes the screen
853882// immediately after executing f.
854883func (a * Application ) QueueUpdateDraw (f func ()) * Application {
@@ -859,6 +888,15 @@ func (a *Application) QueueUpdateDraw(f func()) *Application {
859888 return a
860889}
861890
891+ // QueueUpdateDrawContext works like QueueUpdateContext() except it refreshes the screen
892+ // immediately after executing f.
893+ func (a * Application ) QueueUpdateDrawContext (ctx context.Context , f func ()) error {
894+ return a .QueueUpdateContext (ctx , func () {
895+ f ()
896+ a .draw ()
897+ })
898+ }
899+
862900// QueueEvent sends an event to the Application event loop.
863901//
864902// It is not recommended for event to be nil.
0 commit comments