diff --git a/bar.go b/bar.go index e9baa76..fae5319 100644 --- a/bar.go +++ b/bar.go @@ -35,7 +35,6 @@ total int64 current int64 refill int64 - lastIncrement int64 trimSpace bool completed bool aborted bool @@ -225,7 +224,6 @@ func (b *Bar) SetCurrent(current int64) { select { case b.operateState <- func(s *bState) { - s.lastIncrement = current - s.current s.current = current if s.triggerComplete && s.current >= s.total { s.current = s.total @@ -254,7 +252,6 @@ } select { case b.operateState <- func(s *bState) { - s.lastIncrement = n s.current += n if s.triggerComplete && s.current >= s.total { s.current = s.total @@ -266,25 +263,33 @@ } } -// DecoratorEwmaUpdate updates all EWMA based decorators. Should be -// called on each iteration, because EWMA's unit of measure is an -// iteration's duration. Panics if called before *Bar.Incr... family -// methods. -func (b *Bar) DecoratorEwmaUpdate(dur time.Duration) { - select { - case b.operateState <- func(s *bState) { - if s.lastIncrement > 0 { - s.decoratorEwmaUpdate(dur) - s.lastIncrement = 0 - } else { - panic("increment required before ewma iteration update") - } - }: - case <-b.done: - if b.bs.lastIncrement > 0 { - b.bs.decoratorEwmaUpdate(dur) - b.bs.lastIncrement = 0 - } +// EwmaIncrement is a shorthand for b.EwmaIncrInt64(1, dur). +func (b *Bar) EwmaIncrement(dur time.Duration) { + b.EwmaIncrInt64(1, dur) +} + +// EwmaIncrBy is a shorthand for b.EwmaIncrInt64(int64(n), dur). +func (b *Bar) EwmaIncrBy(n int, dur time.Duration) { + b.EwmaIncrInt64(int64(n), dur) +} + +// EwmaIncrInt64 increments progress by amount of n and updates EWMA based +// decorators by dur of a single iteration. +func (b *Bar) EwmaIncrInt64(n int64, dur time.Duration) { + if n <= 0 { + return + } + select { + case b.operateState <- func(s *bState) { + s.current += n + s.ewmaUpdate(n, dur) + if s.triggerComplete && s.current >= s.total { + s.current = s.total + s.completed = true + go b.forceRefresh(s.manualRefresh) + } + }: + case <-b.done: } } @@ -565,16 +570,16 @@ } } -func (s bState) decoratorEwmaUpdate(dur time.Duration) { +func (s bState) ewmaUpdate(n int64, dur time.Duration) { var wg sync.WaitGroup for i := 0; i < len(s.ewmaDecorators); i++ { switch d := s.ewmaDecorators[i]; i { case len(s.ewmaDecorators) - 1: - d.EwmaUpdate(s.lastIncrement, dur) + d.EwmaUpdate(n, dur) default: wg.Add(1) go func() { - d.EwmaUpdate(s.lastIncrement, dur) + d.EwmaUpdate(n, dur) wg.Done() }() } diff --git a/proxyreader.go b/proxyreader.go index bc3b65a..b0e7720 100644 --- a/proxyreader.go +++ b/proxyreader.go @@ -27,15 +27,14 @@ } type ewmaProxyReader struct { - proxyReader + io.ReadCloser + bar *Bar } func (x ewmaProxyReader) Read(p []byte) (int, error) { start := time.Now() - n, err := x.proxyReader.Read(p) - if n > 0 { - x.bar.DecoratorEwmaUpdate(time.Since(start)) - } + n, err := x.ReadCloser.Read(p) + x.bar.EwmaIncrBy(n, time.Since(start)) return n, err } @@ -46,21 +45,20 @@ func (x ewmaProxyWriterTo) WriteTo(w io.Writer) (int64, error) { start := time.Now() n, err := x.ReadCloser.(io.WriterTo).WriteTo(w) - if n > 0 { - x.bar.DecoratorEwmaUpdate(time.Since(start)) - } + x.bar.EwmaIncrInt64(n, time.Since(start)) return n, err } func newProxyReader(r io.Reader, b *Bar, hasEwma bool) io.ReadCloser { - pr := proxyReader{toReadCloser(r), b} + rc := toReadCloser(r) if hasEwma { - epr := ewmaProxyReader{pr} + epr := ewmaProxyReader{rc, b} if _, ok := r.(io.WriterTo); ok { return ewmaProxyWriterTo{epr} } return epr } + pr := proxyReader{rc, b} if _, ok := r.(io.WriterTo); ok { return proxyWriterTo{pr} } diff --git a/proxywriter.go b/proxywriter.go index 96fe452..f260daf 100644 --- a/proxywriter.go +++ b/proxywriter.go @@ -27,15 +27,14 @@ } type ewmaProxyWriter struct { - proxyWriter + io.WriteCloser + bar *Bar } func (x ewmaProxyWriter) Write(p []byte) (int, error) { start := time.Now() - n, err := x.proxyWriter.Write(p) - if n > 0 { - x.bar.DecoratorEwmaUpdate(time.Since(start)) - } + n, err := x.WriteCloser.Write(p) + x.bar.EwmaIncrBy(n, time.Since(start)) return n, err } @@ -46,21 +45,20 @@ func (x ewmaProxyReaderFrom) ReadFrom(r io.Reader) (int64, error) { start := time.Now() n, err := x.WriteCloser.(io.ReaderFrom).ReadFrom(r) - if n > 0 { - x.bar.DecoratorEwmaUpdate(time.Since(start)) - } + x.bar.EwmaIncrInt64(n, time.Since(start)) return n, err } func newProxyWriter(w io.Writer, b *Bar, hasEwma bool) io.WriteCloser { - pw := proxyWriter{toWriteCloser(w), b} + wc := toWriteCloser(w) if hasEwma { - epw := ewmaProxyWriter{pw} + epw := ewmaProxyWriter{wc, b} if _, ok := w.(io.ReaderFrom); ok { return ewmaProxyReaderFrom{epw} } return epw } + pw := proxyWriter{wc, b} if _, ok := w.(io.ReaderFrom); ok { return proxyReaderFrom{pw} }