GCC Code Coverage Report


Directory: ./
File: Os/Queue.hpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 4 4 100.0%
Functions: 4 4 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 // ======================================================================
2 // \title Os/Queue.hpp
3 // \brief common function definitions for Os::Queue
4 // ======================================================================
5 #ifndef Os_Queue_hpp_
6 #define Os_Queue_hpp_
7
8 #include <Fw/FPrimeBasicTypes.hpp>
9 #include <Fw/Obj/ObjBase.hpp>
10 #include <Fw/Types/Serializable.hpp>
11 #include <Os/Mutex.hpp>
12 #include <Os/Os.hpp>
13 #include <Os/QueueString.hpp>
14 namespace Os {
15 // Forward declaration for registry
16 class QueueRegistry;
17
18 //! \brief QueueHandle parent class
19 class QueueHandle {};
20
21 //! \brief base queue interface
22 //!
23 //! Queues are used internally to fprime in order to support the messaging between components. The
24 //! QueueInterface is used to abstract away from the standard OS-based queue, allowing F prime support
25 //! multiple OSes in a consistent way.
26 //!
27 class QueueInterface {
28 public:
29 //! \brief status returned from the queue send function
30 enum Status {
31 OP_OK, //!< message sent/received okay
32 ALREADY_CREATED, //!< creating an already created queue
33 EMPTY, //!< If non-blocking, all the messages have been drained.
34 UNINITIALIZED, //!< Queue wasn't initialized successfully
35 SIZE_MISMATCH, //!< attempted to send or receive with buffer too large, too small
36 SEND_ERROR, //!< message send error
37 RECEIVE_ERROR, //!< message receive error
38 INVALID_PRIORITY, //!< invalid priority requested
39 FULL, //!< Queue was full when attempting to send a message
40 NOT_SUPPORTED, //!< Queue feature is not supported
41 ALLOCATION_FAILED, //!< required memory could not be allocated
42 UNKNOWN_ERROR //!< Unexpected error; can't match with returns
43 };
44
45 //! \brief message type
46 enum BlockingType {
47 BLOCKING, //!< Message will block until space is available
48 NONBLOCKING //!< Message will return with status when space is unavailable
49 };
50
51 //! \brief default queue interface constructor
52 4439 QueueInterface() = default;
53
54 //! \brief default queue destructor
55 8878 virtual ~QueueInterface() = default;
56
57 //! \brief copy constructor is forbidden
58 QueueInterface(const QueueInterface& other) = delete;
59
60 //! \brief copy constructor is forbidden
61 QueueInterface(const QueueInterface* other) = delete;
62
63 //! \brief assignment operator is forbidden
64 virtual QueueInterface& operator=(const QueueInterface& other) = delete; // NO_CODESONAR (cpp:S3657)
65
66 //! \brief create queue storage
67 //!
68 //! Creates a queue ensuring sufficient storage to hold `depth` messages of `messageSize` size each. Resource
69 //! allocation is dependent on the underlying implementation and users should assume that resource allocation is
70 //! possible.
71 //!
72 //! \param id: identifier for the queue, used for memory allocation
73 //! \param name: name of queue
74 //! \param depth: depth of queue in number of messages
75 //! \param messageSize: size of an individual message
76 //! \return: status of the creation
77 virtual Status create(FwEnumStoreType id,
78 const Fw::ConstStringBase& name,
79 FwSizeType depth,
80 FwSizeType messageSize) = 0;
81
82 //! \brief teardown the queue
83 //!
84 //! Allow for queues to deallocate resources as part of system shutdown. This delegates to the underlying queue
85 //! implementation.
86 virtual void teardown() = 0;
87
88 //! \brief send a message into the queue
89 //!
90 //! Send a message into the queue, providing the message data, size, priority, and blocking type. When
91 //! `blockType` is set to BLOCKING, this call will block on queue full. Otherwise, this will return an error
92 //! status on queue full.
93 //!
94 //! It is invalid to send a null buffer.
95 //! This method will block if the queue is full and blockType is set to BLOCKING
96 //!
97 //! \param buffer: message data
98 //! \param size: size of message data
99 //! \param priority: priority of the message
100 //! \param blockType: BLOCKING to block for space or NONBLOCKING to return error when queue is full
101 //! \return: status of the send
102 virtual Status send(const U8* buffer, FwSizeType size, FwQueuePriorityType priority, BlockingType blockType) = 0;
103
104 //! \brief receive a message from the queue
105 //!
106 //! Receive a message from the queue, providing the message destination, capacity, priority, and blocking type.
107 //! When `blockType` is set to BLOCKING, this call will block on queue empty. Otherwise, this will return an
108 //! error status on queue empty. Actual size received and priority of message is set on success status.
109 //!
110 //! It is invalid to send a null buffer.
111 //! This method will block if the queue is empty and blockType is set to BLOCKING
112 //!
113 //! \param destination: destination for message data
114 //! \param capacity: maximum size of message data
115 //! \param blockType: BLOCKING to wait for message or NONBLOCKING to return error when queue is empty
116 //! \param actualSize: (output) actual size of message read
117 //! \param priority: (output) priority of message read
118 //! \return: status of the send
119 virtual Status receive(U8* destination,
120 FwSizeType capacity,
121 BlockingType blockType,
122 FwSizeType& actualSize,
123 FwQueuePriorityType& priority) = 0;
124
125 //! \brief get number of messages available
126 //!
127 //! Returns the number of messages currently available in the queue.
128 //!
129 //! \return number of messages available
130 virtual FwSizeType getMessagesAvailable() const = 0;
131
132 //! \brief get maximum messages stored at any given time
133 //!
134 //! Returns the maximum number of messages in this queue at any given time. This is the high-water mark for this
135 //! queue.
136 //! \return queue message high-water mark
137 virtual FwSizeType getMessageHighWaterMark() const = 0;
138
139 //! \brief return the underlying queue handle (implementation specific)
140 //! \return internal task handle representation
141 virtual QueueHandle* getHandle() = 0;
142
143 //! \brief provide a pointer to a queue delegate object
144 //!
145 //! This function must return a pointer to a `QueueInterface` object that contains the real implementation of the
146 //! queue functions as defined by the implementor. This function must do several things to be considered correctly
147 //! implemented:
148 //!
149 //! 1. Assert that the supplied memory is non-null. e.g `FW_ASSERT(aligned_placement_new_memory != NULL);`
150 //! 2. Assert that their implementation fits within FW_HANDLE_MAX_SIZE.
151 //! e.g. `static_assert(sizeof(PosixQueueImplementation) <= sizeof Os::Queue::m_handle_storage,
152 //! "FW_HANDLE_MAX_SIZE to small");`
153 //! 3. Assert that their implementation aligns within FW_HANDLE_ALIGNMENT.
154 //! e.g. `static_assert((FW_HANDLE_ALIGNMENT % alignof(PosixQueueImplementation)) == 0, "Bad handle alignment");`
155 //! 4. Placement new their implementation into `aligned_placement_new_memory`
156 //! e.g. `TaskInterface* interface = new (aligned_placement_new_memory) PosixQueueImplementation;`
157 //! 5. Return the result of the placement new
158 //! e.g. `return interface;`
159 //!
160 //! \return result of placement new, must be equivalent to `aligned_placement_new_memory`
161 //!
162 static QueueInterface* getDelegate(QueueHandleStorage& aligned_placement_new_memory);
163 };
164
165 class Queue final : public QueueInterface {
166 public:
167 //! \brief queue constructor
168 Queue();
169
170 //! \brief default queue destructor
171 virtual ~Queue();
172
173 //! \brief copy constructor is forbidden
174 Queue(const Queue& other) = delete;
175
176 //! \brief copy constructor is forbidden
177 Queue(const Queue* other) = delete;
178
179 //! \brief assignment operator is forbidden
180 QueueInterface& operator=(const QueueInterface& other) override = delete;
181
182 //! \brief create queue storage through delegate
183 //!
184 //! Creates a queue ensuring sufficient storage to hold `depth` messages of `messageSize` size each. This method
185 //! delegates to the underlying implementation. Resource allocation is dependent on the underlying implementation
186 //! and users should assume that resource allocation is possible.
187 //!
188 //! \param name: name of queue
189 //! \param depth: depth of queue in number of messages
190 //! \param messageSize: size of an individual message
191 //! \return: status of the creation
192 Status create(FwEnumStoreType id,
193 const Fw::ConstStringBase& name,
194 FwSizeType depth,
195 FwSizeType messageSize) override;
196
197 //! \brief teardown the queue
198 //!
199 //! Allow for queues to deallocate resources as part of system shutdown. This delegates to the underlying queue
200 //! implementation.
201 //! implementation.
202 void teardown() override;
203
204 //! \brief send a message into the queue through delegate
205 //!
206 //! Send a message into the queue, providing the message data, size, priority, and blocking type. When
207 //! `blockType` is set to BLOCKING, this call will block on queue full. Otherwise, this will return an error
208 //! status on queue full. This method delegates to the underlying implementation.
209 //!
210 //! \warning It is invalid to send a null buffer
211 //! \warning This method will block if the queue is full and blockType is set to BLOCKING
212 //!
213 //! \param buffer: message data
214 //! \param size: size of message data
215 //! \param priority: priority of the message
216 //! \param blockType: BLOCKING to block for space or NONBLOCKING to return error when queue is full
217 //! \return: status of the send
218 Status send(const U8* buffer, FwSizeType size, FwQueuePriorityType priority, BlockingType blockType) override;
219
220 //! \brief receive a message from the queue through delegate
221 //!
222 //! Receive a message from the queue, providing the message destination, capacity, priority, and blocking type.
223 //! When `blockType` is set to BLOCKING, this call will block on queue empty. Otherwise, this will return an
224 //! error status on queue empty. Actual size received and priority of message is set on success status. This method
225 //! delegates to the underlying implementation.
226 //!
227 //! \warning It is invalid to send a null buffer.
228 //! \warning This method will block if the queue is empty and blockType is set to BLOCKING
229 //!
230 //! \param destination: destination for message data
231 //! \param capacity: maximum size of message data
232 //! \param blockType: BLOCKING to wait for message or NONBLOCKING to return error when queue is empty
233 //! \param actualSize: (output) actual size of message read
234 //! \param priority: (output) priority of message read
235 //! \return: status of the send
236 Status receive(U8* destination,
237 FwSizeType capacity,
238 BlockingType blockType,
239 FwSizeType& actualSize,
240 FwQueuePriorityType& priority) override;
241
242 //! \brief get number of messages available
243 //!
244 //! Returns the number of messages currently available in the queue. This method delegates to the underlying
245 //! implementation.
246 //!
247 //! \return number of messages available
248 FwSizeType getMessagesAvailable() const override;
249
250 //! \brief get maximum messages stored at any given time through delegate
251 //!
252 //! Returns the maximum number of messages in this queue at any given time. This is the high-water mark for
253 //! this queue.
254 //! \return queue message high-water mark
255 FwSizeType getMessageHighWaterMark() const override;
256
257 //! \brief return the underlying queue handle (implementation specific). Delegates to implementation.
258 //! \return internal task handle representation
259 QueueHandle* getHandle() override;
260
261 //! \brief send a message to a queue
262 //!
263 //! Send a message to a queue with the given priority and block type. See: QueueInterface::send
264 //!
265 //! \warning This method will block if the queue is full and blockType is set to BLOCKING
266 //!
267 //! \param message: reference to serialize buffer storing message
268 //! \param priority: priority of the message
269 //! \param blockType: BLOCKING to block for space or NONBLOCKING to return error when queue is full
270 //! \return status of the send
271 Status send(const Fw::LinearBufferBase& message, FwQueuePriorityType priority, BlockingType blockType);
272
273 //! \brief receive a message from a queue
274 //!
275 //! Receive a message from a queue with the given block type. See: QueueInterface::receive. Note: this will entirely
276 //! overwrite the buffer.
277 //!
278 //! \warning This method will block if the queue is full and blockType is set to BLOCKING
279 //!
280 //! \param destination: reference to serialize buffer for storing message
281 //! \param priority: (output) priority of the message
282 //! \param blockType: BLOCKING to block for space or NONBLOCKING to return error when queue is full
283 //! \return status of the send
284 Status receive(Fw::LinearBufferBase& destination, BlockingType blockType, FwQueuePriorityType& priority);
285
286 //! \brief get the queue's depth in messages
287 FwSizeType getDepth() const;
288
289 //! \brief get the queue's message maximum size
290 FwSizeType getMessageSize() const;
291
292 //! \brief get the queue's name
293 const QueueString& getName() const;
294
295 //! \brief get number of queues system-wide
296 static FwSizeType getNumQueues();
297
298 //! \brief get static mutex
299 static Os::Mutex& getStaticMutex();
300
301 private:
302 QueueString m_name; //!< queue name
303 FwSizeType m_depth; //!< Queue depth
304 FwSizeType m_size; //!< Maximum message size
305 static Os::Mutex s_countLock; //!< Lock the count
306 static FwSizeType s_queueCount; //!< Count of the number of queues
307
308 #if FW_QUEUE_REGISTRATION
309 public:
310 //! \brief set QueueRegistry for tracking queues
311 //!
312 //! \param registry: registry to set
313 static void setRegistry(QueueRegistry* registry);
314
315 private:
316 static QueueRegistry* s_queueRegistry; //!< Queue registry store
317 #endif
318
319 // This section is used to store the implementation-defined file handle. To Os::File and fprime, this type is
320 // opaque and thus normal allocation cannot be done. Instead, we allow the implementor to store then handle in
321 // the byte-array here and set `handle` to that address for storage.
322 //
323 alignas(FW_HANDLE_ALIGNMENT) QueueHandleStorage m_handle_storage; //!< Storage for aligned handle
324 QueueInterface& m_delegate; //!< Delegate for the real implementation
325 };
326 //! \brief queue registry interface
327 //!
328 //! The QueueRegistry is used to track queues in the system. There is intended to be a single, global, queue registry
329 //! across the system. It is used to track queues and will receive a callback on the creation of each queue.
330 class QueueRegistry {
331 public:
332 //! Default QueueRegistry
333 30 QueueRegistry() = default;
334 //! Default ~QueueRegistry
335 60 virtual ~QueueRegistry() = default;
336
337 //! \brief queue registry callback
338 //!
339 //! Register the queue with this queue registry. Must be implemented by QueueRegistry implementations.
340 //!
341 //! \param queue: queue being registered
342 virtual void registerQueue(Queue* queue) = 0; //!< method called by queue init() methods to register a new queue
343 };
344 } // namespace Os
345 #endif
346