GCC Code Coverage Report


Directory: Utils/
File: Types/Queue.cpp
Date: 2026-09-23 21:15:08
Exec Total Coverage
Lines: 0 104 0.0%
Functions: 0 20 0.0%
Branches: 0 48 0.0%

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 ✗ Queue::Queue() : m_internal(), m_message_size(0), m_mode(QUEUE_FIFO), m_overflow_mode(QUEUE_DROP_NEWEST) {}
16
17 ✗ 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 ✗ const FwSizeType total_needed_size = depth * message_size;
25 ✗ FW_ASSERT(storage_size >= total_needed_size, static_cast<FwAssertArgType>(storage_size),
26 static_cast<FwAssertArgType>(depth), static_cast<FwAssertArgType>(message_size));
27 ✗ FW_ASSERT(mode == QUEUE_FIFO || mode == QUEUE_LIFO, static_cast<FwAssertArgType>(mode));
28 ✗ FW_ASSERT(overflow_mode == QUEUE_DROP_OLDEST || overflow_mode == QUEUE_DROP_NEWEST,
29 static_cast<FwAssertArgType>(overflow_mode));
30 ✗ m_internal.setup(storage, total_needed_size);
31 ✗ m_message_size = message_size;
32 ✗ m_mode = mode;
33 ✗ m_overflow_mode = overflow_mode;
34 ✗ }
35
36 ✗ Fw::SerializeStatus Queue::enqueue(const U8* const message, const FwSizeType size) {
37 ✗ FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size)); // Ensure initialization
38 ✗ FW_ASSERT(m_message_size == size, static_cast<FwAssertArgType>(size),
39 static_cast<FwAssertArgType>(m_message_size)); // Message size is as expected
40 ✗ FW_ASSERT(message != nullptr);
41 ✗ 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 ✗ if (status == Fw::FW_SERIALIZE_NO_ROOM_LEFT && m_overflow_mode == QUEUE_DROP_OLDEST) {
45 // Remove the oldest message by rotating
46 ✗ Fw::SerializeStatus rotate_status = m_internal.rotate(m_message_size);
47 ✗ 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 ✗ status = m_internal.serialize(message, m_message_size);
53 ✗ if (status != Fw::FW_SERIALIZE_OK) {
54 ✗ return status;
55 } else {
56 // Let the caller know we deleted data
57 ✗ return Fw::FW_SERIALIZE_DISCARDED_EXISTING;
58 }
59 }
60
61 ✗ return status;
62 }
63
64 template <typename T>
65 ✗ Fw::SerializeStatus Queue::enqueue_impl(const T& message) {
66 ✗ FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size)); // Ensure initialization
67 ✗ 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 ✗ if (status == Fw::FW_SERIALIZE_NO_ROOM_LEFT && m_overflow_mode == QUEUE_DROP_OLDEST) {
71 // Remove the oldest message by rotating
72 ✗ Fw::SerializeStatus rotate_status = m_internal.rotate(m_message_size);
73 ✗ 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 ✗ status = m_internal.serialize(message, m_message_size);
79 ✗ if (status != Fw::FW_SERIALIZE_OK) {
80 ✗ return status;
81 } else {
82 // Let the caller know we deleted data
83 ✗ return Fw::FW_SERIALIZE_DISCARDED_EXISTING;
84 }
85 }
86
87 ✗ return status;
88 }
89
90 ✗ Fw::SerializeStatus Queue::enqueue(const Fw::Serializable& message) {
91 ✗ return this->enqueue_impl(message);
92 }
93
94 ✗ Fw::SerializeStatus Queue::enqueue(const Fw::LinearBufferBase& message) {
95 ✗ return this->enqueue_impl(message);
96 }
97
98 ✗ Fw::SerializeStatus Queue::dequeue(U8* const message, const FwSizeType size) {
99 ✗ FW_ASSERT(m_message_size > 0); // Ensure initialization
100 ✗ FW_ASSERT(m_message_size <= size, static_cast<FwAssertArgType>(size),
101 static_cast<FwAssertArgType>(m_message_size)); // Sufficient storage space for read message
102 ✗ FW_ASSERT(message != nullptr);
103 Fw::SerializeStatus result;
104
105 ✗ if (m_mode == QUEUE_FIFO) {
106 // FIFO: Dequeue from the front (oldest message)
107 ✗ result = m_internal.peek(message, m_message_size, 0);
108 ✗ if (result != Fw::FW_SERIALIZE_OK) {
109 ✗ return result;
110 }
111 ✗ return m_internal.rotate(m_message_size);
112 } else {
113 // LIFO: Dequeue from the back (newest message)
114 ✗ FwSizeType current_size = m_internal.get_allocated_size();
115 ✗ if (current_size < m_message_size) {
116 ✗ return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
117 }
118 ✗ FwSizeType offset = current_size - m_message_size;
119 ✗ result = m_internal.peek(message, m_message_size, offset);
120 ✗ if (result != Fw::FW_SERIALIZE_OK) {
121 ✗ return result;
122 }
123 ✗ return m_internal.trim(m_message_size);
124 }
125 }
126
127 template <typename T>
128 ✗ Fw::SerializeStatus Queue::dequeue_impl(T& message) {
129 ✗ FW_ASSERT(m_message_size > 0); // Ensure initialization
130 Fw::SerializeStatus result;
131
132 ✗ if (m_mode == QUEUE_FIFO) {
133 // FIFO: Dequeue from the front (oldest message)
134 ✗ result = m_internal.peek(message, m_message_size, 0);
135 ✗ if (result != Fw::FW_SERIALIZE_OK) {
136 ✗ return result;
137 }
138 ✗ return m_internal.rotate(m_message_size);
139 } else {
140 // LIFO: Dequeue from the back (newest message)
141 ✗ FwSizeType current_size = m_internal.get_allocated_size();
142 ✗ if (current_size < m_message_size) {
143 ✗ return Fw::FW_DESERIALIZE_BUFFER_EMPTY;
144 }
145 ✗ FwSizeType offset = current_size - m_message_size;
146 ✗ result = m_internal.peek(message, m_message_size, offset);
147 ✗ if (result != Fw::FW_SERIALIZE_OK) {
148 ✗ return result;
149 }
150 ✗ return m_internal.trim(m_message_size);
151 }
152 }
153
154 ✗ Fw::SerializeStatus Queue::dequeue(Fw::Serializable& message) {
155 ✗ return this->dequeue_impl(message);
156 }
157
158 ✗ Fw::SerializeStatus Queue::dequeue(Fw::LinearBufferBase& message) {
159 ✗ return this->dequeue_impl(message);
160 }
161
162 ✗ Fw::SerializeStatus Queue::popFront(U8* const message, const FwSizeType size) {
163 ✗ FW_ASSERT(m_message_size > 0);
164 ✗ FW_ASSERT(m_message_size <= size, static_cast<FwAssertArgType>(size), static_cast<FwAssertArgType>(m_message_size));
165 ✗ FW_ASSERT(message != nullptr);
166 // Always remove from the front (oldest), regardless of queue mode
167 ✗ Fw::SerializeStatus result = m_internal.peek(message, m_message_size, 0);
168 ✗ if (result != Fw::FW_SERIALIZE_OK) {
169 ✗ return result;
170 }
171 ✗ return m_internal.rotate(m_message_size);
172 }
173
174 template <typename T>
175 ✗ Fw::SerializeStatus Queue::popFront_impl(T& message) {
176 ✗ FW_ASSERT(m_message_size > 0);
177 // Always remove from the front (oldest), regardless of queue mode
178 ✗ Fw::SerializeStatus result = m_internal.peek(message, m_message_size, 0);
179 ✗ if (result != Fw::FW_SERIALIZE_OK) {
180 ✗ return result;
181 }
182 ✗ return m_internal.rotate(m_message_size);
183 }
184
185 ✗ Fw::SerializeStatus Queue::popFront(Fw::Serializable& message) {
186 ✗ return this->popFront_impl(message);
187 }
188
189 ✗ Fw::SerializeStatus Queue::popFront(Fw::LinearBufferBase& message) {
190 ✗ return this->popFront_impl(message);
191 }
192
193 ✗ FwSizeType Queue::get_high_water_mark() const {
194 ✗ FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size));
195 ✗ return m_internal.get_high_water_mark() / m_message_size;
196 }
197
198 ✗ void Queue::clear_high_water_mark() {
199 ✗ m_internal.clear_high_water_mark();
200 ✗ }
201
202 ✗ FwSizeType Queue::getQueueSize() const {
203 ✗ FW_ASSERT(m_message_size > 0, static_cast<FwAssertArgType>(m_message_size));
204 ✗ return m_internal.get_allocated_size() / m_message_size;
205 }
206
207 } // namespace Types
208