GCC Code Coverage Report


Directory: ./
File: Utils/RateLimiter.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 0 73 0.0%
Functions: 0 15 0.0%
Branches: 0 50 0.0%

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 RateLimiter ::RateLimiter(U32 counterCycle, U32 timeCycle) : m_counterCycle(counterCycle), m_timeCycle(timeCycle) {
17 this->reset();
18 }
19
20 RateLimiter ::RateLimiter() : m_counterCycle(0), m_timeCycle(0) {
21 this->reset();
22 }
23
24 void RateLimiter ::setCounterCycle(U32 counterCycle) {
25 this->m_counterCycle = counterCycle;
26 }
27
28 void RateLimiter ::setTimeCycle(U32 timeCycle) {
29 this->m_timeCycle = timeCycle;
30 }
31
32 void RateLimiter ::reset() {
33 this->resetCounter();
34 this->resetTime();
35 }
36
37 void RateLimiter ::resetCounter() {
38 this->m_counter = 0;
39 }
40
41 void RateLimiter ::resetTime() {
42 this->m_time = Fw::Time();
43 this->m_timeAtNegativeInfinity = true;
44 }
45
46 void RateLimiter ::setCounter(U32 counter) {
47 this->m_counter = counter;
48 }
49
50 void RateLimiter ::setTime(Fw::Time time) {
51 this->m_time = time;
52 this->m_timeAtNegativeInfinity = false;
53 }
54
55 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 if (this->m_counterCycle == 0 && this->m_timeCycle == 0) {
67 return true;
68 }
69
70 // evaluate trigger criteria
71 bool shouldTrigger = false;
72 if (this->m_counterCycle > 0) {
73 shouldTrigger = shouldTrigger || this->shouldCounterTrigger();
74 }
75 if (this->m_timeCycle > 0) {
76 shouldTrigger = shouldTrigger || this->shouldTimeTrigger(time);
77 }
78
79 // update states
80 if (this->m_counterCycle > 0) {
81 this->updateCounter(shouldTrigger);
82 }
83 if (this->m_timeCycle > 0) {
84 this->updateTime(shouldTrigger, time);
85 }
86
87 return shouldTrigger;
88 }
89
90 bool RateLimiter ::trigger() {
91 FW_ASSERT(this->m_timeCycle == 0);
92 return trigger(Fw::Time::zero());
93 }
94
95 bool RateLimiter ::shouldCounterTrigger() {
96 FW_ASSERT(this->m_counterCycle > 0);
97
98 // trigger at 0
99 bool shouldTrigger = (this->m_counter == 0);
100
101 return shouldTrigger;
102 }
103
104 bool RateLimiter ::shouldTimeTrigger(Fw::Time time) {
105 FW_ASSERT(this->m_timeCycle > 0);
106
107 // trigger at prev trigger time + time cycle seconds OR when time is at negative infinity
108 Fw::Time timeCycle = Fw::Time(this->m_timeCycle, 0);
109 Fw::Time nextTrigger = Fw::Time::add(this->m_time, timeCycle);
110 bool shouldTrigger = (time >= nextTrigger) || this->m_timeAtNegativeInfinity;
111
112 return shouldTrigger;
113 }
114
115 void RateLimiter ::updateCounter(bool triggered) {
116 FW_ASSERT(this->m_counterCycle > 0);
117
118 if (triggered) {
119 // triggered, set to next state and maybe wrap (handles counterCycle == 1)
120 this->m_counter = 1;
121 if (this->m_counter >= this->m_counterCycle) {
122 this->m_counter = 0;
123 }
124
125 } else {
126 // otherwise, just increment and maybe wrap
127 this->m_counter++;
128 if (this->m_counter >= this->m_counterCycle) {
129 this->m_counter = 0;
130 }
131 }
132 }
133
134 void RateLimiter ::updateTime(bool triggered, Fw::Time time) {
135 FW_ASSERT(this->m_timeCycle > 0);
136
137 if (triggered) {
138 // mark time of trigger
139 this->m_time = time;
140 }
141 this->m_timeAtNegativeInfinity = false;
142 }
143
144 } // end namespace Utils
145