1package decor 2 3import ( 4 "sort" 5 "sync" 6 7 "github.com/VividCortex/ewma" 8) 9 10type threadSafeMovingAverage struct { 11 ewma.MovingAverage 12 mu sync.Mutex 13} 14 15func (s *threadSafeMovingAverage) Add(value float64) { 16 s.mu.Lock() 17 s.MovingAverage.Add(value) 18 s.mu.Unlock() 19} 20 21func (s *threadSafeMovingAverage) Value() float64 { 22 s.mu.Lock() 23 defer s.mu.Unlock() 24 return s.MovingAverage.Value() 25} 26 27func (s *threadSafeMovingAverage) Set(value float64) { 28 s.mu.Lock() 29 s.MovingAverage.Set(value) 30 s.mu.Unlock() 31} 32 33// NewThreadSafeMovingAverage converts provided ewma.MovingAverage 34// into thread safe ewma.MovingAverage. 35func NewThreadSafeMovingAverage(average ewma.MovingAverage) ewma.MovingAverage { 36 if tsma, ok := average.(*threadSafeMovingAverage); ok { 37 return tsma 38 } 39 return &threadSafeMovingAverage{MovingAverage: average} 40} 41 42type medianWindow [3]float64 43 44func (s *medianWindow) Len() int { return len(s) } 45func (s *medianWindow) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 46func (s *medianWindow) Less(i, j int) bool { return s[i] < s[j] } 47 48func (s *medianWindow) Add(value float64) { 49 s[0], s[1] = s[1], s[2] 50 s[2] = value 51} 52 53func (s *medianWindow) Value() float64 { 54 tmp := *s 55 sort.Sort(&tmp) 56 return tmp[1] 57} 58 59func (s *medianWindow) Set(value float64) { 60 for i := 0; i < len(s); i++ { 61 s[i] = value 62 } 63} 64 65// NewMedian is fixed last 3 samples median MovingAverage. 66func NewMedian() ewma.MovingAverage { 67 return NewThreadSafeMovingAverage(new(medianWindow)) 68} 69