Overte C++ Documentation
SimpleMovingAverage.h
1 //
2 // SimpleMovingAverage.h
3 // libraries/shared/src
4 //
5 // Created by Stephen Birarda on 4/18/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Replaces Brad Hefta-Gaub's CounterStats class (RIP)
9 //
10 // Distributed under the Apache License, Version 2.0.
11 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
12 //
13 
14 #ifndef hifi_SimpleMovingAverage_h
15 #define hifi_SimpleMovingAverage_h
16 
17 #include <mutex>
18 #include <stdint.h>
19 #include <atomic>
20 
21 class SimpleMovingAverage {
22 public:
23  SimpleMovingAverage(int numSamplesToAverage = 100);
24  SimpleMovingAverage(const SimpleMovingAverage& other);
25  SimpleMovingAverage& operator=(const SimpleMovingAverage& other);
26 
27  int updateAverage(float sample);
28  void reset();
29 
30  int getSampleCount() const { return _numSamples; };
31  float getAverage() const { return _average; };
32  float getEventDeltaAverage() const; // returned in seconds
33  float getAverageSampleValuePerSecond() const { return _average * (1.0f / getEventDeltaAverage()); }
34 
35  uint64_t getUsecsSinceLastEvent() const;
36 
37 
38 private:
39  std::atomic<int> _numSamples;
40  std::atomic<uint64_t> _lastEventTimestamp;
41  std::atomic<float> _average;
42  std::atomic<float> _eventDeltaAverage;
43 
44  float WEIGHTING;
45  float ONE_MINUS_WEIGHTING;
46 };
47 
48 
49 template <class T, int MAX_NUM_SAMPLES> class MovingAverage {
50 public:
51  MovingAverage() {}
52  MovingAverage(const MovingAverage<T, MAX_NUM_SAMPLES>& other) {
53  *this = other;
54  }
55  MovingAverage<T, MAX_NUM_SAMPLES>& operator=(const MovingAverage<T, MAX_NUM_SAMPLES>& other) {
56  numSamples = (int)other.numSamples;
57  average = (T)other.average;
58  return *this;
59  }
60 
61  const float WEIGHTING = 1.0f / (float)MAX_NUM_SAMPLES;
62  const float ONE_MINUS_WEIGHTING = 1.0f - WEIGHTING;
63  std::atomic<int> numSamples{ 0 };
64  std::atomic<T> average;
65 
66  void clear() {
67  numSamples = 0;
68  }
69 
70  bool isAverageValid() const { return (numSamples > 0); }
71 
72  void addSample(T sample) {
73  if (numSamples > 0) {
74  average = (sample * (T)WEIGHTING) + (average * (T)ONE_MINUS_WEIGHTING);
75  } else {
76  average = sample;
77  }
78  numSamples++;
79  }
80 };
81 
82 template <class T, int MAX_NUM_SAMPLES> class ThreadSafeMovingAverage {
83 public:
84  void clear() {
85  std::unique_lock<std::mutex> lock(_lock);
86  _samples = 0;
87  }
88 
89  bool isAverageValid() const {
90  std::unique_lock<std::mutex> lock(_lock);
91  return (_samples > 0);
92  }
93 
94  void addSample(T sample) {
95  std::unique_lock<std::mutex> lock(_lock);
96  if (_samples > 0) {
97  _average = (sample * WEIGHTING) + (_average * ONE_MINUS_WEIGHTING);
98  } else {
99  _average = sample;
100  }
101  _samples++;
102  }
103 
104  T getAverage() const {
105  std::unique_lock<std::mutex> lock(_lock);
106  return _average;
107  }
108 
109  size_t getSamples() const {
110  std::unique_lock<std::mutex> lock(_lock);
111  return _samples;
112  }
113 
114 private:
115  const float WEIGHTING = 1.0f / (float)MAX_NUM_SAMPLES;
116  const float ONE_MINUS_WEIGHTING = 1.0f - WEIGHTING;
117  size_t _samples { 0 };
118  T _average;
119  mutable std::mutex _lock;
120 };
121 
122 
123 #endif // hifi_SimpleMovingAverage_h