diff --git a/bar.go b/bar.go index dabe1a4..376c2cd 100644 --- a/bar.go +++ b/bar.go @@ -8,6 +8,7 @@ "log" "runtime/debug" "strings" + "sync" "time" "github.com/acarl005/stripansi" @@ -50,8 +51,7 @@ total int64 current int64 refill int64 - lastN int64 - iterated bool + lastIncrement int64 trimSpace bool completed bool completeFlushed bool @@ -189,8 +189,7 @@ func (b *Bar) SetCurrent(current int64) { select { case b.operateState <- func(s *bState) { - s.iterated = true - s.lastN = current - s.current + s.lastIncrement = current - s.current s.current = current if s.triggerComplete && s.current >= s.total { s.current = s.total @@ -214,10 +213,12 @@ // IncrInt64 increments progress by amount of n. func (b *Bar) IncrInt64(n int64) { - select { - case b.operateState <- func(s *bState) { - s.iterated = true - s.lastN = n + if n <= 0 { + return + } + select { + case b.operateState <- func(s *bState) { + s.lastIncrement = n s.current += n if s.triggerComplete && s.current >= s.total { s.current = s.total @@ -236,10 +237,18 @@ func (b *Bar) DecoratorEwmaUpdate(dur time.Duration) { select { case b.operateState <- func(s *bState) { - ewmaIterationUpdate(false, s, dur) - }: - case <-b.done: - ewmaIterationUpdate(true, b.cacheState, dur) + if s.lastIncrement > 0 { + s.decoratorEwmaUpdate(dur) + s.lastIncrement = 0 + } else { + panic("increment required before ewma iteration update") + } + }: + case <-b.done: + if b.cacheState.lastIncrement > 0 { + b.cacheState.decoratorEwmaUpdate(dur) + b.cacheState.lastIncrement = 0 + } } } @@ -249,9 +258,7 @@ func (b *Bar) DecoratorAverageAdjust(start time.Time) { select { case b.operateState <- func(s *bState) { - for _, d := range s.averageDecorators { - d.AverageAdjust(start) - } + s.decoratorAverageAdjust(start) }: case <-b.done: } @@ -321,10 +328,7 @@ case op := <-b.operateState: op(s) case <-ctx.Done(): - // Notifying decorators about shutdown event - for _, sl := range s.shutdownListeners { - sl.Shutdown() - } + s.decoratorShutdownNotify() b.cacheState = s close(b.done) return @@ -481,6 +485,45 @@ return table } +func (s bState) decoratorEwmaUpdate(dur time.Duration) { + wg := new(sync.WaitGroup) + wg.Add(len(s.ewmaDecorators)) + for _, d := range s.ewmaDecorators { + d := d + go func() { + d.EwmaUpdate(s.lastIncrement, dur) + wg.Done() + }() + } + wg.Wait() +} + +func (s bState) decoratorAverageAdjust(start time.Time) { + wg := new(sync.WaitGroup) + wg.Add(len(s.averageDecorators)) + for _, d := range s.averageDecorators { + d := d + go func() { + d.AverageAdjust(start) + wg.Done() + }() + } + wg.Wait() +} + +func (s bState) decoratorShutdownNotify() { + wg := new(sync.WaitGroup) + wg.Add(len(s.shutdownListeners)) + for _, d := range s.shutdownListeners { + d := d + go func() { + d.Shutdown() + wg.Done() + }() + } + wg.Wait() +} + func newStatistics(tw int, s *bState) decor.Statistics { return decor.Statistics{ ID: s.id, @@ -497,17 +540,6 @@ return extractBaseDecorator(d.Base()) } return d -} - -func ewmaIterationUpdate(done bool, s *bState, dur time.Duration) { - if !done && !s.iterated { - panic("increment required before ewma iteration update") - } else { - s.iterated = false - } - for _, d := range s.ewmaDecorators { - d.EwmaUpdate(s.lastN, dur) - } } func makePanicExtender(p interface{}) extenderFunc {