| Line | Branch | Exec | Source |
|---|---|---|---|
| 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 | |||
| 12 | #include <Utils/RateLimiter.hpp> | ||
| 13 | |||
| 14 | namespace Utils { | ||
| 15 | |||
| 16 | 17 | RateLimiter ::RateLimiter(U32 counterCycle, U32 timeCycle) : m_counterCycle(counterCycle), m_timeCycle(timeCycle) { | |
| 17 |
1/1✓ Branch 2 taken 17 times.
|
17 | this->reset(); |
| 18 | 17 | } | |
| 19 | |||
| 20 | 2 | RateLimiter ::RateLimiter() : m_counterCycle(0), m_timeCycle(0) { | |
| 21 |
1/1✓ Branch 2 taken 2 times.
|
2 | this->reset(); |
| 22 | 2 | } | |
| 23 | |||
| 24 | 1 | void RateLimiter ::setCounterCycle(U32 counterCycle) { | |
| 25 | 1 | this->m_counterCycle = counterCycle; | |
| 26 | 1 | } | |
| 27 | |||
| 28 | 1 | void RateLimiter ::setTimeCycle(U32 timeCycle) { | |
| 29 | 1 | this->m_timeCycle = timeCycle; | |
| 30 | 1 | } | |
| 31 | |||
| 32 | 45 | void RateLimiter ::reset() { | |
| 33 | 45 | this->resetCounter(); | |
| 34 | 45 | this->resetTime(); | |
| 35 | 45 | } | |
| 36 | |||
| 37 | 45 | void RateLimiter ::resetCounter() { | |
| 38 | 45 | this->m_counter = 0; | |
| 39 | 45 | } | |
| 40 | |||
| 41 | 45 | void RateLimiter ::resetTime() { | |
| 42 |
2/2✓ Branch 2 taken 45 times.
✓ Branch 11 taken 45 times.
|
45 | this->m_time = Fw::Time(); |
| 43 | 45 | this->m_timeAtNegativeInfinity = true; | |
| 44 | 45 | } | |
| 45 | |||
| 46 | 3 | void RateLimiter ::setCounter(U32 counter) { | |
| 47 | 3 | this->m_counter = counter; | |
| 48 | 3 | } | |
| 49 | |||
| 50 | 4 | void RateLimiter ::setTime(Fw::Time time) { | |
| 51 | 4 | this->m_time = time; | |
| 52 | 4 | this->m_timeAtNegativeInfinity = false; | |
| 53 | 4 | } | |
| 54 | |||
| 55 | 1340138 | bool RateLimiter ::trigger(Fw::Time time) { | |
| 56 | // NB: this implements a 4-bit decision, logically equivalent to this pseudo-code | ||
| 57 | // | ||
| 58 | // A = HAS_COUNTER, B = HAS_TIME, C = COUNTER_TRIGGER, D = TIME_TRIGGER | ||
| 59 | // | ||
| 60 | // if (!A && !B) => true | ||
| 61 | // if (A && B) => C || D | ||
| 62 | // if (A) => C | ||
| 63 | // if (B) => D | ||
| 64 | // false | ||
| 65 | // | ||
| 66 |
4/4✓ Branch 1 taken 410023 times.
✓ Branch 2 taken 930115 times.
✓ Branch 5 taken 110012 times.
✓ Branch 6 taken 300011 times.
|
1340138 | if (this->m_counterCycle == 0 && this->m_timeCycle == 0) { |
| 67 | 110012 | return true; | |
| 68 | } | ||
| 69 | |||
| 70 | // evaluate trigger criteria | ||
| 71 | 1230126 | bool shouldTrigger = false; | |
| 72 |
2/2✓ Branch 1 taken 930115 times.
✓ Branch 2 taken 300011 times.
|
1230126 | if (this->m_counterCycle > 0) { |
| 73 |
3/4✓ Branch 0 taken 930115 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 10308 times.
✓ Branch 5 taken 919807 times.
|
930115 | shouldTrigger = shouldTrigger || this->shouldCounterTrigger(); |
| 74 | } | ||
| 75 |
2/2✓ Branch 2 taken 1200020 times.
✓ Branch 3 taken 30106 times.
|
1230126 | if (this->m_timeCycle > 0) { |
| 76 |
10/14✓ Branch 0 taken 1191953 times.
✓ Branch 1 taken 8067 times.
✓ Branch 5 taken 1191953 times.
✓ Branch 8 taken 1191953 times.
✓ Branch 10 taken 11819 times.
✓ Branch 11 taken 1180134 times.
✓ Branch 12 taken 1191953 times.
✓ Branch 13 taken 8067 times.
✓ Branch 16 taken 1191953 times.
✓ Branch 17 taken 8067 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
|
1200020 | shouldTrigger = shouldTrigger || this->shouldTimeTrigger(time); |
| 77 | } | ||
| 78 | |||
| 79 | // update states | ||
| 80 |
2/2✓ Branch 1 taken 930115 times.
✓ Branch 2 taken 300011 times.
|
1230126 | if (this->m_counterCycle > 0) { |
| 81 | 930115 | this->updateCounter(shouldTrigger); | |
| 82 | } | ||
| 83 |
2/2✓ Branch 2 taken 1200020 times.
✓ Branch 3 taken 30106 times.
|
1230126 | if (this->m_timeCycle > 0) { |
| 84 |
2/2✓ Branch 3 taken 1200020 times.
✓ Branch 6 taken 1200020 times.
|
1200020 | this->updateTime(shouldTrigger, time); |
| 85 | } | ||
| 86 | |||
| 87 | 1230126 | return shouldTrigger; | |
| 88 | } | ||
| 89 | |||
| 90 | 40117 | bool RateLimiter ::trigger() { | |
| 91 | 40117 | FW_ASSERT(this->m_timeCycle == 0); | |
| 92 |
3/3✓ Branch 4 taken 40117 times.
✓ Branch 7 taken 40117 times.
✓ Branch 10 taken 40117 times.
|
40117 | return trigger(Fw::Time::zero()); |
| 93 | } | ||
| 94 | |||
| 95 | 930115 | bool RateLimiter ::shouldCounterTrigger() { | |
| 96 | 930115 | FW_ASSERT(this->m_counterCycle > 0); | |
| 97 | |||
| 98 | // trigger at 0 | ||
| 99 | 930115 | bool shouldTrigger = (this->m_counter == 0); | |
| 100 | |||
| 101 | 930115 | return shouldTrigger; | |
| 102 | } | ||
| 103 | |||
| 104 | 1191953 | bool RateLimiter ::shouldTimeTrigger(Fw::Time time) { | |
| 105 | 1191953 | FW_ASSERT(this->m_timeCycle > 0); | |
| 106 | |||
| 107 | // trigger at prev trigger time + time cycle seconds OR when time is at negative infinity | ||
| 108 |
1/1✓ Branch 4 taken 1191953 times.
|
1191953 | Fw::Time timeCycle = Fw::Time(this->m_timeCycle, 0); |
| 109 |
1/1✓ Branch 5 taken 1191953 times.
|
1191953 | Fw::Time nextTrigger = Fw::Time::add(this->m_time, timeCycle); |
| 110 |
6/7✓ Branch 3 taken 1191953 times.
✓ Branch 5 taken 1180141 times.
✓ Branch 6 taken 11812 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1180141 times.
✓ Branch 10 taken 7 times.
✓ Branch 11 taken 1180134 times.
|
1191953 | bool shouldTrigger = (time >= nextTrigger) || this->m_timeAtNegativeInfinity; |
| 111 | |||
| 112 | 1191953 | return shouldTrigger; | |
| 113 | 1191953 | } | |
| 114 | |||
| 115 | 930115 | void RateLimiter ::updateCounter(bool triggered) { | |
| 116 | 930115 | FW_ASSERT(this->m_counterCycle > 0); | |
| 117 | |||
| 118 |
2/2✓ Branch 0 taken 15646 times.
✓ Branch 1 taken 914469 times.
|
930115 | if (triggered) { |
| 119 | // triggered, set to next state and maybe wrap (handles counterCycle == 1) | ||
| 120 | 15646 | this->m_counter = 1; | |
| 121 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 15646 times.
|
15646 | if (this->m_counter >= this->m_counterCycle) { |
| 122 | ✗ | this->m_counter = 0; | |
| 123 | } | ||
| 124 | |||
| 125 | } else { | ||
| 126 | // otherwise, just increment and maybe wrap | ||
| 127 | 914469 | this->m_counter++; | |
| 128 |
2/2✓ Branch 3 taken 10286 times.
✓ Branch 4 taken 904183 times.
|
914469 | if (this->m_counter >= this->m_counterCycle) { |
| 129 | 10286 | this->m_counter = 0; | |
| 130 | } | ||
| 131 | } | ||
| 132 | 930115 | } | |
| 133 | |||
| 134 | 1200020 | void RateLimiter ::updateTime(bool triggered, Fw::Time time) { | |
| 135 | 1200020 | FW_ASSERT(this->m_timeCycle > 0); | |
| 136 | |||
| 137 |
2/2✓ Branch 0 taken 19886 times.
✓ Branch 1 taken 1180134 times.
|
1200020 | if (triggered) { |
| 138 | // mark time of trigger | ||
| 139 | 19886 | this->m_time = time; | |
| 140 | } | ||
| 141 | 1200020 | this->m_timeAtNegativeInfinity = false; | |
| 142 | 1200020 | } | |
| 143 | |||
| 144 | } // end namespace Utils | ||
| 145 |