diff --git a/backend/app.go b/backend/app.go index 4d66c90..e1e71b5 100644 --- a/backend/app.go +++ b/backend/app.go @@ -504,6 +504,12 @@ func (a *App) DeleteServerCacheDir(serverID uuid.UUID) error { return os.RemoveAll(path) } +// BackgroundContext returns the application's background context +// which is canceled when the application shuts down. +func (a *App) BackgroundContext() context.Context { + return a.bgrndCtx +} + func (a *App) Shutdown() { if a.logFile != nil { a.logFile.Close() diff --git a/ui/browsing/router.go b/ui/browsing/router.go index 0530e7c..7d16c38 100644 --- a/ui/browsing/router.go +++ b/ui/browsing/router.go @@ -26,7 +26,7 @@ func NewRouter(app *backend.App, controller *controller.Controller, nav Navigati App: app, Controller: controller, Nav: nav, - widgetPool: util.NewWidgetPool(), + widgetPool: util.NewWidgetPool(app.BackgroundContext()), } return r } diff --git a/ui/util/widgetpool.go b/ui/util/widgetpool.go index d41e69e..a81d1cc 100644 --- a/ui/util/widgetpool.go +++ b/ui/util/widgetpool.go @@ -1,6 +1,7 @@ package util import ( + "context" "sync" "time" @@ -31,8 +32,9 @@ const ( // A pool to share commonly-used widgets across pages to reduce // creation of new widgets and memory allocations. type WidgetPool struct { - mut sync.Mutex - pools [][]pooledWidget + mut sync.Mutex + pools [][]pooledWidget + cancel context.CancelFunc } type pooledWidget struct { @@ -40,14 +42,22 @@ type pooledWidget struct { releasedAt int64 // unixMillis } -func NewWidgetPool() *WidgetPool { +func NewWidgetPool(ctx context.Context) *WidgetPool { + ctx, cancel := context.WithCancel(ctx) p := &WidgetPool{ - pools: make([][]pooledWidget, numWidgetTypes), + pools: make([][]pooledWidget, numWidgetTypes), + cancel: cancel, } go func() { t := time.NewTicker(2 * time.Minute) - for range t.C { - p.cleanUpExpiredItems() + defer t.Stop() + for { + select { + case <-ctx.Done(): + return + case <-t.C: + p.cleanUpExpiredItems() + } } }() return p