RateLimiter.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // ======================================================================
  2. // \title RateLimiter.cpp
  3. // \author vwong
  4. // \brief cpp file for a rate limiter utility class
  5. //
  6. // \copyright
  7. // Copyright (C) 2009-2020 California Institute of Technology.
  8. // ALL RIGHTS RESERVED. United States Government Sponsorship
  9. // acknowledged.
  10. // ======================================================================
  11. #include <Utils/RateLimiter.hpp>
  12. namespace Utils {
  13. RateLimiter ::
  14. RateLimiter (
  15. U32 counterCycle,
  16. U32 timeCycle
  17. ) :
  18. m_counterCycle(counterCycle),
  19. m_timeCycle(timeCycle)
  20. {
  21. this->reset();
  22. }
  23. RateLimiter ::
  24. RateLimiter () :
  25. m_counterCycle(0),
  26. m_timeCycle(0)
  27. {
  28. this->reset();
  29. }
  30. void RateLimiter ::
  31. setCounterCycle(
  32. U32 counterCycle
  33. )
  34. {
  35. this->m_counterCycle = counterCycle;
  36. }
  37. void RateLimiter ::
  38. setTimeCycle(
  39. U32 timeCycle
  40. )
  41. {
  42. this->m_timeCycle = timeCycle;
  43. }
  44. void RateLimiter ::
  45. reset()
  46. {
  47. this->resetCounter();
  48. this->resetTime();
  49. }
  50. void RateLimiter ::
  51. resetCounter()
  52. {
  53. this->m_counter = 0;
  54. }
  55. void RateLimiter ::
  56. resetTime()
  57. {
  58. this->m_time = Fw::Time();
  59. this->m_timeAtNegativeInfinity = true;
  60. }
  61. void RateLimiter ::
  62. setCounter(
  63. U32 counter
  64. )
  65. {
  66. this->m_counter = counter;
  67. }
  68. void RateLimiter ::
  69. setTime(
  70. Fw::Time time
  71. )
  72. {
  73. this->m_time = time;
  74. this->m_timeAtNegativeInfinity = false;
  75. }
  76. bool RateLimiter ::
  77. trigger(
  78. Fw::Time time
  79. )
  80. {
  81. // NB: this implements a 4-bit decision, logically equivalent to this pseudo-code
  82. //
  83. // A = HAS_COUNTER, B = HAS_TIME, C = COUNTER_TRIGGER, D = TIME_TRIGGER
  84. //
  85. // if (!A && !B) => true
  86. // if (A && B) => C || D
  87. // if (A) => C
  88. // if (B) => D
  89. // false
  90. //
  91. if (this->m_counterCycle == 0 && this->m_timeCycle == 0) {
  92. return true;
  93. }
  94. // evaluate trigger criteria
  95. bool shouldTrigger = false;
  96. if (this->m_counterCycle > 0) {
  97. shouldTrigger = shouldTrigger || this->shouldCounterTrigger();
  98. }
  99. if (this->m_timeCycle > 0) {
  100. shouldTrigger = shouldTrigger || this->shouldTimeTrigger(time);
  101. }
  102. // update states
  103. if (this->m_counterCycle > 0) {
  104. this->updateCounter(shouldTrigger);
  105. }
  106. if (this->m_timeCycle > 0) {
  107. this->updateTime(shouldTrigger, time);
  108. }
  109. return shouldTrigger;
  110. }
  111. bool RateLimiter ::
  112. trigger()
  113. {
  114. FW_ASSERT(this->m_timeCycle == 0);
  115. return trigger(Fw::Time::zero());
  116. }
  117. bool RateLimiter ::
  118. shouldCounterTrigger()
  119. {
  120. FW_ASSERT(this->m_counterCycle > 0);
  121. // trigger at 0
  122. bool shouldTrigger = (this->m_counter == 0);
  123. return shouldTrigger;
  124. }
  125. bool RateLimiter ::
  126. shouldTimeTrigger(Fw::Time time)
  127. {
  128. FW_ASSERT(this->m_timeCycle > 0);
  129. // trigger at prev trigger time + time cycle seconds OR when time is at negative infinity
  130. Fw::Time timeCycle = Fw::Time(this->m_timeCycle, 0);
  131. Fw::Time nextTrigger = Fw::Time::add(this->m_time, timeCycle);
  132. bool shouldTrigger = (time >= nextTrigger) || this->m_timeAtNegativeInfinity;
  133. return shouldTrigger;
  134. }
  135. void RateLimiter ::
  136. updateCounter(bool triggered)
  137. {
  138. FW_ASSERT(this->m_counterCycle > 0);
  139. if (triggered) {
  140. // triggered, set to next state
  141. this->m_counter = 1;
  142. } else {
  143. // otherwise, just increment and maybe wrap
  144. if (++this->m_counter >= this->m_counterCycle) {
  145. this->m_counter = 0;
  146. }
  147. }
  148. }
  149. void RateLimiter ::
  150. updateTime(bool triggered, Fw::Time time)
  151. {
  152. FW_ASSERT(this->m_timeCycle > 0);
  153. if (triggered) {
  154. // mark time of trigger
  155. this->m_time = time;
  156. }
  157. this->m_timeAtNegativeInfinity = false;
  158. }
  159. } // end namespace Utils