diff --git a/decor/eta.go b/decor/eta.go index f0c97dd..6cb27a2 100644 --- a/decor/eta.go +++ b/decor/eta.go @@ -23,9 +23,9 @@ } // EwmaETA exponential-weighted-moving-average based ETA decorator. -// Note that it's necessary to supply bar.Incr* methods with incremental -// work duration as second argument, in order for this decorator to -// work correctly. This decorator is a wrapper of MovingAverageETA. +// For this decorator to work correctly you have to measure each +// iteration's duration and pass it to the +// *Bar.DecoratorEwmaUpdate(time.Duration) method after each increment. func EwmaETA(style TimeStyle, age float64, wcc ...WC) Decorator { var average ewma.MovingAverage if age == 0 { @@ -33,8 +33,7 @@ } else { average = ewma.NewMovingAverage(age) } - average = &ThreadSafeMovingAverage{MovingAverage: average} - return MovingAverageETA(style, average, nil, wcc...) + return MovingAverageETA(style, NewThreadSafeMovingAverage(average), nil, wcc...) } // MovingAverageETA decorator relies on MovingAverage implementation to calculate its average. diff --git a/decor/moving_average.go b/decor/moving_average.go index 5d2d3a0..50ac9c3 100644 --- a/decor/moving_average.go +++ b/decor/moving_average.go @@ -7,28 +7,36 @@ "github.com/VividCortex/ewma" ) -// ThreadSafeMovingAverage is a thread safe wrapper for ewma.MovingAverage. -type ThreadSafeMovingAverage struct { +type threadSafeMovingAverage struct { ewma.MovingAverage mu sync.Mutex } -func (s *ThreadSafeMovingAverage) Add(value float64) { +func (s *threadSafeMovingAverage) Add(value float64) { s.mu.Lock() s.MovingAverage.Add(value) s.mu.Unlock() } -func (s *ThreadSafeMovingAverage) Value() float64 { +func (s *threadSafeMovingAverage) Value() float64 { s.mu.Lock() defer s.mu.Unlock() return s.MovingAverage.Value() } -func (s *ThreadSafeMovingAverage) Set(value float64) { +func (s *threadSafeMovingAverage) Set(value float64) { s.mu.Lock() s.MovingAverage.Set(value) s.mu.Unlock() +} + +// NewThreadSafeMovingAverage converts provided ewma.MovingAverage +// into thread safe ewma.MovingAverage. +func NewThreadSafeMovingAverage(average ewma.MovingAverage) ewma.MovingAverage { + if tsma, ok := average.(*threadSafeMovingAverage); ok { + return tsma + } + return &threadSafeMovingAverage{MovingAverage: average} } type medianWindow [3]float64 @@ -56,5 +64,5 @@ // NewMedian is fixed last 3 samples median MovingAverage. func NewMedian() ewma.MovingAverage { - return &ThreadSafeMovingAverage{MovingAverage: new(medianWindow)} + return NewThreadSafeMovingAverage(new(medianWindow)) } diff --git a/decor/speed.go b/decor/speed.go index 142e5be..8a48e3f 100644 --- a/decor/speed.go +++ b/decor/speed.go @@ -28,9 +28,9 @@ } // EwmaSpeed exponential-weighted-moving-average based speed decorator. -// Note that it's necessary to supply bar.Incr* methods with incremental -// work duration as second argument, in order for this decorator to -// work correctly. This decorator is a wrapper of MovingAverageSpeed. +// For this decorator to work correctly you have to measure each +// iteration's duration and pass it to the +// *Bar.DecoratorEwmaUpdate(time.Duration) method after each increment. func EwmaSpeed(unit int, format string, age float64, wcc ...WC) Decorator { var average ewma.MovingAverage if age == 0 { @@ -38,8 +38,7 @@ } else { average = ewma.NewMovingAverage(age) } - average = &ThreadSafeMovingAverage{MovingAverage: average} - return MovingAverageSpeed(unit, format, average, wcc...) + return MovingAverageSpeed(unit, format, NewThreadSafeMovingAverage(average), wcc...) } // MovingAverageSpeed decorator relies on MovingAverage implementation