GCC Code Coverage Report


Directory: Utils/Types/
File: Queue.cpp
Date: 2026-09-03 21:18:40
Exec Total Coverage
Lines: 95 104 91.3%
Functions: 18 20 90.0%
Branches: 35 48 72.9%

Line Branch Exec Source
1 /*
2 * Queue.cpp:
3 *
4 * Implementation of the queue data type.
5 *
6 * Created on: July 5th, 2022
7 * Author: lestarch
8 *
9 */
10 #include "Queue.hpp"
11 #include <Fw/Types/Assert.hpp>
12
13 namespace Types {
14
15 24 Queue::Queue() : m_internal(), m_message_size(0), m_mode(QUEUE_FIFO), m_overflow_mode(QUEUE_DROP_NEWEST) {}
16
17 24 void Queue::setup(U8* const storage,
18 const FwSizeType storage_size,
19 const FwSizeType depth,
20 const FwSizeType message_size,
21 const QueueMode mode,
22 const QueueOverflowMode overflow_mode) {
23 // Ensure that enough storage was supplied
24 24 const FwSizeType total_needed_size = depth * message_size;
25 24 FW_ASSERT(storage_size >= total_needed_size, static_cast<FwAssertArgType>(storage_size),
26 static_cast<FwAssertArgType>(depth), static_cast<FwAssertArgType>(message_size));
27 24 FW_ASSERT(mode == QUEUE_FIFO || mode == QUEUE_LIFO, static_cast<FwAssertArgType>(mode));
28 24 FW_ASSERT(overflow_mode == QUEUE_DROP_OLDEST || overflow_mode == QUEUE_DROP_NEWEST,
29 static_cast<FwAssertArgType>(overflow_mode));
30 24 m_internal.setup(storage, total_needed_size);
31 24 m_message_size = message_size;
32 24 m_mode = mode;
33 24 m_overflow_mode = overflow_mode;
34 24 }
35
36 9916 Fw::SerializeStatus Queue::enqueue(const U8* const message, const FwSizeType size) {
37 9916 FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size)); // Ensure initialization
38 9916 FW_ASSERT(m_message_size == size, static_cast<FwAssertArgType>(size),
39 static_cast<FwAssertArgType>(m_message_size)); // Message size is as expected
40 9916 FW_ASSERT(message != nullptr);
41 9916 Fw::SerializeStatus status = m_internal.serialize(message, m_message_size);
42
43 // If queue is full and we're in DROP_OLDEST mode, remove the oldest and try again
44
5/6
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 9744 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 172 times.
✓ Branch 5 taken 76 times.
✓ Branch 6 taken 96 times.
9916 if (status == Fw::FW_SERIALIZE_NO_ROOM_LEFT && m_overflow_mode == QUEUE_DROP_OLDEST) {
45 // Remove the oldest message by rotating
46 76 Fw::SerializeStatus rotate_status = m_internal.rotate(m_message_size);
47
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (rotate_status != Fw::FW_SERIALIZE_OK) {
48 return rotate_status;
49 }
50
51 // Now enqueue the new message (should succeed since we just freed space)
52 76 status = m_internal.serialize(message, m_message_size);
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (status != Fw::FW_SERIALIZE_OK) {
54 return status;
55 } else {
56 // Let the caller know we deleted data
57 76 return Fw::FW_SERIALIZE_DISCARDED_EXISTING;
58 }
59 }
60
61 9840 return status;
62 }
63
64 template <typename T>
65 262 Fw::SerializeStatus Queue::enqueue_impl(const T& message) {
66 262 FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size)); // Ensure initialization
67 262 Fw::SerializeStatus status = m_internal.serialize(message, m_message_size);
68
69 // If queue is full and we're in DROP_OLDEST mode, remove the oldest and try again
70
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 128 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
262 if (status == Fw::FW_SERIALIZE_NO_ROOM_LEFT && m_overflow_mode == QUEUE_DROP_OLDEST) {
71 // Remove the oldest message by rotating
72 2 Fw::SerializeStatus rotate_status = m_internal.rotate(m_message_size);
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
2 if (rotate_status != Fw::FW_SERIALIZE_OK) {
74 return rotate_status;
75 }
76
77 // Now enqueue the new message (should succeed since we just freed space)
78 2 status = m_internal.serialize(message, m_message_size);
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
2 if (status != Fw::FW_SERIALIZE_OK) {
80 return status;
81 } else {
82 // Let the caller know we deleted data
83 2 return Fw::FW_SERIALIZE_DISCARDED_EXISTING;
84 }
85 }
86
87 260 return status;
88 }
89
90 75 Fw::SerializeStatus Queue::enqueue(const Fw::Serializable& message) {
91 75 return this->enqueue_impl(message);
92 }
93
94 56 Fw::SerializeStatus Queue::enqueue(const Fw::LinearBufferBase& message) {
95 56 return this->enqueue_impl(message);
96 }
97
98 10045 Fw::SerializeStatus Queue::dequeue(U8* const message, const FwSizeType size) {
99 10045 FW_ASSERT(m_message_size > 0); // Ensure initialization
100 10045 FW_ASSERT(m_message_size <= size, static_cast<FwAssertArgType>(size),
101 static_cast<FwAssertArgType>(m_message_size)); // Sufficient storage space for read message
102 10045 FW_ASSERT(message != nullptr);
103 Fw::SerializeStatus result;
104
105
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 10045 times.
✓ Branch 3 taken 5012 times.
✓ Branch 4 taken 5033 times.
10045 if (m_mode == QUEUE_FIFO) {
106 // FIFO: Dequeue from the front (oldest message)
107 5012 result = m_internal.peek(message, m_message_size, 0);
108
2/2
✓ Branch 0 taken 2555 times.
✓ Branch 1 taken 2457 times.
5012 if (result != Fw::FW_SERIALIZE_OK) {
109 2555 return result;
110 }
111 2457 return m_internal.rotate(m_message_size);
112 } else {
113 // LIFO: Dequeue from the back (newest message)
114 5033 FwSizeType current_size = m_internal.get_allocated_size();
115
2/2
✓ Branch 2 taken 2636 times.
✓ Branch 3 taken 2397 times.
5033 if (current_size < m_message_size) {
116 2636 return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
117 }
118 2397 FwSizeType offset = current_size - m_message_size;
119 2397 result = m_internal.peek(message, m_message_size, offset);
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2397 times.
2397 if (result != Fw::FW_SERIALIZE_OK) {
121 return result;
122 }
123 2397 return m_internal.trim(m_message_size);
124 }
125 }
126
127 template <typename T>
128 240 Fw::SerializeStatus Queue::dequeue_impl(T& message) {
129 240 FW_ASSERT(m_message_size > 0); // Ensure initialization
130 Fw::SerializeStatus result;
131
132
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 115 times.
✓ Branch 4 taken 5 times.
240 if (m_mode == QUEUE_FIFO) {
133 // FIFO: Dequeue from the front (oldest message)
134 230 result = m_internal.peek(message, m_message_size, 0);
135
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 114 times.
230 if (result != Fw::FW_SERIALIZE_OK) {
136 2 return result;
137 }
138 228 return m_internal.rotate(m_message_size);
139 } else {
140 // LIFO: Dequeue from the back (newest message)
141 10 FwSizeType current_size = m_internal.get_allocated_size();
142
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
10 if (current_size < m_message_size) {
143 return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
144 }
145 10 FwSizeType offset = current_size - m_message_size;
146 10 result = m_internal.peek(message, m_message_size, offset);
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
10 if (result != Fw::FW_SERIALIZE_OK) {
148 return result;
149 }
150 10 return m_internal.trim(m_message_size);
151 }
152 }
153
154 65 Fw::SerializeStatus Queue::dequeue(Fw::Serializable& message) {
155 65 return this->dequeue_impl(message);
156 }
157
158 55 Fw::SerializeStatus Queue::dequeue(Fw::LinearBufferBase& message) {
159 55 return this->dequeue_impl(message);
160 }
161
162 10018 Fw::SerializeStatus Queue::popFront(U8* const message, const FwSizeType size) {
163 10018 FW_ASSERT(m_message_size > 0);
164 10018 FW_ASSERT(m_message_size <= size, static_cast<FwAssertArgType>(size), static_cast<FwAssertArgType>(m_message_size));
165 10018 FW_ASSERT(message != nullptr);
166 // Always remove from the front (oldest), regardless of queue mode
167 10018 Fw::SerializeStatus result = m_internal.peek(message, m_message_size, 0);
168
2/2
✓ Branch 0 taken 5131 times.
✓ Branch 1 taken 4887 times.
10018 if (result != Fw::FW_SERIALIZE_OK) {
169 5131 return result;
170 }
171 4887 return m_internal.rotate(m_message_size);
172 }
173
174 template <typename T>
175 6 Fw::SerializeStatus Queue::popFront_impl(T& message) {
176 6 FW_ASSERT(m_message_size > 0);
177 // Always remove from the front (oldest), regardless of queue mode
178 6 Fw::SerializeStatus result = m_internal.peek(message, m_message_size, 0);
179
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
6 if (result != Fw::FW_SERIALIZE_OK) {
180 2 return result;
181 }
182 4 return m_internal.rotate(m_message_size);
183 }
184
185 3 Fw::SerializeStatus Queue::popFront(Fw::Serializable& message) {
186 3 return this->popFront_impl(message);
187 }
188
189 Fw::SerializeStatus Queue::popFront(Fw::LinearBufferBase& message) {
190 return this->popFront_impl(message);
191 }
192
193 10102 FwSizeType Queue::get_high_water_mark() const {
194 10102 FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size));
195
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 10102 times.
10102 return m_internal.get_high_water_mark() / m_message_size;
196 }
197
198 1059 void Queue::clear_high_water_mark() {
199 1059 m_internal.clear_high_water_mark();
200 1059 }
201
202 10103 FwSizeType Queue::getQueueSize() const {
203 10103 FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size));
204
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 10103 times.
10103 return m_internal.get_allocated_size() / m_message_size;
205 }
206
207 } // namespace Types
208