diff --git a/bar.go b/bar.go index 19274d8..7d41873 100644 --- a/bar.go +++ b/bar.go @@ -36,13 +36,13 @@ priority int index int - runningBar *Bar - cacheState *bState - operateState chan func(*bState) - bFrameCh chan *bFrame - syncTableCh chan [][]chan int - intValue chan int64 - completed chan bool + runningBar *Bar + cacheState *bState + operateState chan func(*bState) + bFrameCh chan *bFrame + syncTableCh chan [][]chan int + completed chan bool + forceRefreshCh chan time.Time // done is closed by Bar's goroutine, after cacheState is written done chan struct{} @@ -91,6 +91,7 @@ func newBar( ctx context.Context, wg *sync.WaitGroup, + forceRefreshCh chan time.Time, filler Filler, id, width int, total int64, @@ -122,15 +123,15 @@ } b := &Bar{ - priority: s.priority, - runningBar: s.runningBar, - operateState: make(chan func(*bState)), - bFrameCh: make(chan *bFrame, 1), - syncTableCh: make(chan [][]chan int), - intValue: make(chan int64), - completed: make(chan bool), - done: make(chan struct{}), - shutdown: make(chan struct{}), + priority: s.priority, + runningBar: s.runningBar, + operateState: make(chan func(*bState)), + bFrameCh: make(chan *bFrame, 1), + syncTableCh: make(chan [][]chan int), + completed: make(chan bool), + done: make(chan struct{}), + shutdown: make(chan struct{}), + forceRefreshCh: forceRefreshCh, } if b.runningBar != nil { @@ -171,9 +172,10 @@ // ID returs id of the bar. func (b *Bar) ID() int { - select { - case b.operateState <- func(s *bState) { b.intValue <- int64(s.id) }: - return int(<-b.intValue) + result := make(chan int) + select { + case b.operateState <- func(s *bState) { result <- s.id }: + return <-result case <-b.done: return b.cacheState.id } @@ -181,9 +183,10 @@ // Current returns bar's current number, in other words sum of all increments. func (b *Bar) Current() int64 { - select { - case b.operateState <- func(s *bState) { b.intValue <- s.current }: - return <-b.intValue + result := make(chan int64) + select { + case b.operateState <- func(s *bState) { result <- s.current }: + return <-result case <-b.done: return b.cacheState.current } @@ -209,6 +212,7 @@ if final { s.current = s.total s.toComplete = true + go b.forceRefresh() } }: return true @@ -246,6 +250,7 @@ if s.current >= s.total { s.current = s.total s.toComplete = true + go b.forceRefresh() } for _, ar := range s.amountReceivers { ar.NextAmount(n, wdd...) @@ -406,6 +411,13 @@ return table } +func (b *Bar) forceRefresh() { + select { + case b.forceRefreshCh <- time.Now(): + case <-b.shutdown: + } +} + func newStatistics(s *bState) *decor.Statistics { return &decor.Statistics{ ID: s.id, diff --git a/progress.go b/progress.go index 176a0a5..63a69c1 100644 --- a/progress.go +++ b/progress.go @@ -62,8 +62,8 @@ width: pwidth, rr: prr, waitBars: make(map[*Bar]*Bar), + forceRefreshCh: make(chan time.Time), debugOut: ioutil.Discard, - forceRefreshCh: make(chan time.Time), output: os.Stdout, } @@ -105,7 +105,7 @@ result := make(chan *Bar) select { case p.operateState <- func(s *pState) { - b := newBar(s.ctx, p.bwg, filler, s.idCounter, s.width, total, options...) + b := newBar(s.ctx, p.bwg, s.forceRefreshCh, filler, s.idCounter, s.width, total, options...) if b.runningBar != nil { s.waitBars[b.runningBar] = b } else { @@ -232,14 +232,6 @@ frame := <-bar.bFrameCh defer func() { if frame.toShutdown { - go func() { - // force next refresh, so it will be triggered either by ticker or by - // this goroutine, whichever comes first - select { - case s.forceRefreshCh <- time.Now(): - case <-bar.done: - } - }() // shutdown at next flush, in other words decrement underlying WaitGroup // only after the bar with completed state has been flushed. this // ensures no bar ends up with less than 100% rendered.