diff --git a/bar.go b/bar.go index f6cba15..972fd54 100644 --- a/bar.go +++ b/bar.go @@ -44,7 +44,6 @@ rmOnComplete bool noPop bool autoRefresh bool - manualRefresh bool aDecorators []decor.Decorator pDecorators []decor.Decorator averageDecorators []decor.AverageDecorator @@ -458,7 +457,7 @@ // one hour for example and bar completes within a few minutes p.Wait() // will wait for one hour. This call helps to avoid unnecessary waiting. go b.tryEarlyRefresh(s.refreshCh) - } else if !s.manualRefresh { + } else { b.cancel() } } diff --git a/container_option.go b/container_option.go index 6664e53..ad98711 100644 --- a/container_option.go +++ b/container_option.go @@ -41,21 +41,7 @@ // Refresh will occur upon receive value from provided ch. func WithManualRefresh(ch <-chan interface{}) ContainerOption { return func(s *pState) { - s.manualRefresh = true - go func(refreshCh chan<- time.Time, done <-chan struct{}) { - for { - select { - case x := <-ch: - if t, ok := x.(time.Time); ok { - refreshCh <- t - } else { - refreshCh <- time.Now() - } - case <-done: - return - } - } - }(s.refreshCh, s.ctx.Done()) + s.manualRC = ch } } diff --git a/progress.go b/progress.go index 1e3b41b..42db17f 100644 --- a/progress.go +++ b/progress.go @@ -44,9 +44,9 @@ refreshRate time.Duration reqWidth int popCompleted bool - manualRefresh bool autoRefresh bool renderDelay <-chan struct{} + manualRC <-chan interface{} shutdownNotifier chan<- interface{} queueBars map[*Bar]*Bar output io.Writer @@ -84,26 +84,32 @@ } } - go s.hm.run() - - cw := cwriter.New(s.output) - if (cw.IsTerminal() || s.autoRefresh) && !s.manualRefresh { - s.autoRefresh = true - go s.newTicker(s.renderDelay != nil) - } else { - s.autoRefresh = false - } - p := &Progress{ uwg: s.uwg, operateState: make(chan func(*pState)), interceptIO: make(chan func(io.Writer)), - done: ctx.Done(), cancel: cancel, + } + + cw := cwriter.New(s.output) + if s.manualRC != nil { + done := make(chan struct{}) + p.done = done + s.autoRefresh = false + go s.manualRefreshListener(done) + } else if cw.IsTerminal() || s.autoRefresh { + done := make(chan struct{}) + p.done = done + s.autoRefresh = true + go s.autoRefreshListener(done) + } else { + p.done = s.ctx.Done() + s.autoRefresh = false } p.pwg.Add(1) go p.serve(s, cw) + go s.hm.run() return p } @@ -267,8 +273,8 @@ } } -func (s *pState) newTicker(delay bool) { - if delay { +func (s pState) autoRefreshListener(done chan struct{}) { + if s.renderDelay != nil { <-s.renderDelay } ticker := time.NewTicker(s.refreshRate) @@ -278,6 +284,23 @@ case t := <-ticker.C: s.refreshCh <- t case <-s.ctx.Done(): + close(done) + return + } + } +} + +func (s pState) manualRefreshListener(done chan struct{}) { + for { + select { + case x := <-s.manualRC: + if t, ok := x.(time.Time); ok { + s.refreshCh <- t + } else { + s.refreshCh <- time.Now() + } + case <-s.ctx.Done(): + close(done) return } } @@ -385,14 +408,13 @@ func (s *pState) makeBarState(total int64, filler BarFiller, options ...BarOption) *bState { bs := &bState{ - id: s.idCount, - priority: s.idCount, - reqWidth: s.reqWidth, - total: total, - filler: filler, - refreshCh: s.refreshCh, - autoRefresh: s.autoRefresh, - manualRefresh: s.manualRefresh, + id: s.idCount, + priority: s.idCount, + reqWidth: s.reqWidth, + total: total, + filler: filler, + refreshCh: s.refreshCh, + autoRefresh: s.autoRefresh, } if total > 0 {