diff --git a/bar.go b/bar.go index 27da6bf..d8c59d2 100644 --- a/bar.go +++ b/bar.go @@ -31,16 +31,13 @@ type Bar struct { priority int index int - // quit channel to request b.server to quit - quit chan struct{} - // done channel is receiveable after b.server has been quit - done chan struct{} + operateState chan func(*bState) + quit chan struct{} + once sync.Once // cacheState is used after b.done is receiveable cacheState *bState - - once sync.Once } type ( @@ -99,9 +96,8 @@ b := &Bar{ priority: id, + operateState: make(chan func(*bState)), quit: make(chan struct{}), - done: make(chan struct{}), - operateState: make(chan func(*bState)), } go b.serve(s, wg, cancel) @@ -194,7 +190,7 @@ select { case b.operateState <- func(s *bState) { result <- len(s.appendFuncs) }: return <-result - case <-b.done: + case <-b.quit: return len(b.cacheState.appendFuncs) } } @@ -205,7 +201,7 @@ select { case b.operateState <- func(s *bState) { result <- len(s.prependFuncs) }: return <-result - case <-b.done: + case <-b.quit: return len(b.cacheState.prependFuncs) } } @@ -216,7 +212,7 @@ select { case b.operateState <- func(s *bState) { result <- s.id }: return <-result - case <-b.done: + case <-b.quit: return b.cacheState.id } } @@ -227,7 +223,7 @@ select { case b.operateState <- func(s *bState) { result <- s.current }: return <-result - case <-b.done: + case <-b.quit: return b.cacheState.current } } @@ -238,7 +234,7 @@ select { case b.operateState <- func(s *bState) { result <- s.total }: return <-result - case <-b.done: + case <-b.quit: return b.cacheState.total } } @@ -275,15 +271,12 @@ } func (b *Bar) shutdown() { - close(b.quit) + b.quit <- struct{}{} + <-b.quit } func (b *Bar) serve(s *bState, wg *sync.WaitGroup, cancel <-chan struct{}) { - defer func() { - b.cacheState = s - close(b.done) - wg.Done() - }() + defer wg.Done() for { select { @@ -292,8 +285,10 @@ case <-cancel: s.aborted = true cancel = nil - b.Complete() + go b.Complete() case <-b.quit: + b.cacheState = s + close(b.quit) return } } @@ -319,7 +314,7 @@ s.draw(tw, prependWs, appendWs) ch <- &bufReader{io.MultiReader(s.bufP, s.bufB, s.bufA), s.completed} }: - case <-b.done: + case <-b.quit: s := b.cacheState var r io.Reader if s.panic != "" { diff --git a/progress.go b/progress.go index 363b084..dace329 100644 --- a/progress.go +++ b/progress.go @@ -26,11 +26,9 @@ // External wg ewg *sync.WaitGroup - // quit channel to request p.server to quit - quit chan struct{} - // done channel is receiveable after p.server has been quit - done chan struct{} operateState chan func(*pState) + quit chan struct{} + once sync.Once } type ( @@ -82,7 +80,6 @@ p := &Progress{ ewg: s.ewg, wg: new(sync.WaitGroup), - done: make(chan struct{}), operateState: make(chan func(*pState)), quit: make(chan struct{}), } @@ -160,25 +157,14 @@ if p.ewg != nil { p.ewg.Wait() } - select { - case <-p.quit: - return - default: - // wait for all bars to quit - p.wg.Wait() - // request p.server to quit - p.quitRequest() - // wait for p.server to quit - <-p.done - } -} - -func (p *Progress) quitRequest() { - select { - case <-p.quit: - default: - close(p.quit) - } + // wait for all bars to quit + p.wg.Wait() + p.once.Do(p.shutdown) +} + +func (p *Progress) shutdown() { + p.quit <- struct{}{} + <-p.quit } func newWidthSync(timeout <-chan struct{}, numBars, numColumn int) *widthSync { diff --git a/progress_posix.go b/progress_posix.go index 7a8027e..a32723b 100644 --- a/progress_posix.go +++ b/progress_posix.go @@ -16,14 +16,6 @@ func (p *Progress) serve(s *pState) { winch := make(chan os.Signal, 1) signal.Notify(winch, syscall.SIGWINCH) - - defer func() { - if s.shutdownNotifier != nil { - close(s.shutdownNotifier) - } - signal.Stop(winch) - close(p.done) - }() var numP, numA int var timer *time.Timer @@ -67,10 +59,16 @@ case <-s.cancel: s.ticker.Stop() s.cancel = nil + // don't return here, p.Stop() must be called eventually case <-p.quit: if s.cancel != nil { s.ticker.Stop() } + if s.shutdownNotifier != nil { + close(s.shutdownNotifier) + } + signal.Stop(winch) + close(p.quit) return } } diff --git a/progress_windows.go b/progress_windows.go index 907d8bb..b3f8ab0 100644 --- a/progress_windows.go +++ b/progress_windows.go @@ -11,12 +11,6 @@ ) func (p *Progress) serve(s *pState) { - defer func() { - if s.shutdownNotifier != nil { - close(s.shutdownNotifier) - } - close(p.done) - }() var numP, numA int @@ -42,10 +36,15 @@ case <-s.cancel: s.ticker.Stop() s.cancel = nil + // don't return here, p.Stop() must be called eventually case <-p.quit: if s.cancel != nil { s.ticker.Stop() } + if s.shutdownNotifier != nil { + close(s.shutdownNotifier) + } + close(p.quit) return } }