FreeRTOScpp
QueueCPP.h
Go to the documentation of this file.
1 /**
2  * @file QueueCPP.h
3  * @brief FreeRTOS Queue Wrapper
4  *
5  * This file contains a set of lightweight wrappers for queues using FreeRTOS
6  *
7  * @copyright (c) 2007-2024 Richard Damon
8  * @author Richard Damon <richard.damon@gmail.com>
9  * @parblock
10  * MIT License:
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28  * THE SOFTWARE.
29  *
30  * It is requested (but not required by license) that any bugs found or
31  * improvements made be shared, preferably to the author.
32  * @endparblock
33  *
34  * @ingroup FreeRTOSCpp
35  */
36 #ifndef QUEUECPP_H
37 #define QUEUECPP_H
38 
39 #include "FreeRTOScpp.h"
40 #include "queue.h"
41 
42 #if FREERTOSCPP_USE_NAMESPACE
43 namespace FreeRTOScpp {
44 #endif
45 
46 //#include <type_traits>
47 /**
48  * @brief Base Queue Wrapper
49  *
50  * This Base Class provides the Type Independent functionality for a Queue
51  * @ingroup FreeRTOSCpp
52  */
53 
54 class QueueBase {
55 protected:
56  /**
57  * @brief Constructor
58  *
59  * Effectively Abstract class so protected base.
60  * @param handle_ The queueHandle for the queue/
61  */
62  QueueBase(QueueHandle_t handle_) : queueHandle(handle_) {};
63 public:
64  /**
65  * @brief Destructor.
66  */
67  virtual ~QueueBase() {
68  vQueueDelete(queueHandle);
69  }
70 
71  /**
72  * @brief Get number of items in the Queue.
73  * @return The number of item in the Queue.
74  */
75  unsigned waiting() const {
76  return uxQueueMessagesWaiting(queueHandle);
77  }
78 
79  /**
80  * @brief Return number of spaces available in Queue
81  * @return the number of spaces available in the Queue.
82  */
83  unsigned available() const {
84  return uxQueueSpacesAvailable(queueHandle);
85  }
86 
87  /**
88  * @brief Reset the Queue.
89  * Resets the Queue to an empty state.
90  */
91  void reset() {
92  xQueueReset(queueHandle);
93  }
94 
95  /**
96  * @brief Check if Queue is Full.
97  * @return True if Queue is Full.
98  */
99  bool full() {
100  return 0 == uxQueueSpacesAvailable(queueHandle);
101  }
102 
103  /**
104  * @brief Check if Queue is Empty
105  * @return True if Queue is Empty.
106  */
107  bool empty() {
108  return uxQueueMessagesWaiting(queueHandle) == 0;
109  }
110 
111  /**
112  * @brief Is Queue Full.
113  * Note: Interrupt service routines should only call _ISR routines.
114  * @return True if Queue is Full.
115  */
116  bool full_ISR() {
117  return xQueueIsQueueFullFromISR(queueHandle);
118  }
119 
120  /**
121  * @brief Is Queue Empty.
122  * Note: Interrupt service routines should only call _ISR routines.
123  * @return True if Queue is Empty.
124  */
125  bool empty_ISR() {
126  return xQueueIsQueueEmptyFromISR(queueHandle);
127  }
128 
129  /**
130  * @brief Get number of message waiting.
131  * Note: Interrupt service routines should only call _ISR routines.
132  * @return The number of messages waiting.
133  */
134  unsigned waiting_ISR() {
135  return uxQueueMessagesWaitingFromISR(queueHandle);
136  }
137 
138 protected:
139  QueueHandle_t queueHandle;
140 private:
141 
142 #if __cplusplus < 201101L
143  QueueBase(QueueBase const&); ///< We are not copyable.
144  void operator =(QueueBase const&); ///< We are not assignable.
145 #else
146  QueueBase(QueueBase const&) = delete; ///< We are not copyable.
147  void operator =(QueueBase const&) = delete; ///< We are not assignable.
148 #endif // __cplusplus
149 
150 };
151 
152 /**
153  * @brief Typed Queue Wrapper
154  *
155  * This Base Class provides the Type Dependent functionality for a Queue
156  * @ingroup FreeRTOSCpp
157  */
158 
159 template<class T> class QueueTypeBase : public QueueBase {
160 protected:
161  QueueTypeBase(QueueHandle_t handle_) : QueueBase(handle_) {}
162 
163 public:
164  /**
165  * @brief Push an item onto the Queue.
166  * Puts an item onto the Queue so it will be the next item to remove.
167  * @param item The item to put on the Queue.
168  * @param time How long to wait for room if Queue is full.
169  * @return True if successful
170  */
171  bool push(T const& item, TickType_t time = portMAX_DELAY){
172  return xQueueSendToFront(queueHandle, &item, time);
173  }
174 #if FREERTOSCPP_USE_CHRONO
175  /**
176  * @brief Push an item onto the Queue.
177  * Puts an item onto the Queue so it will be the next item to remove.
178  * @param item The item to put on the Queue.
179  * @param time How long to wait for room if Queue is full.
180  * @return True if successful
181  */
182  bool push(T const& item, Time_ms time){
183  return xQueueSendToFront(queueHandle, &item, ms2ticks(time));
184  }
185 #endif
186  /**
187  * @brief add an item at end of the Queue.
188  * Puts an item onto the Queue so it will be the last item to remove.
189  * @param item The item to put on the Queue.
190  * @param time How long to wait for room if Queue is full.
191  * @return True if successful
192  */
193  bool add(T const& item, TickType_t time = portMAX_DELAY){
194  return xQueueSendToBack(queueHandle, &item, time);
195  }
196 #if FREERTOSCPP_USE_CHRONO
197  /**
198  * @brief add an item at end of the Queue.
199  * Puts an item onto the Queue so it will be the last item to remove.
200  * @param item The item to put on the Queue.
201  * @param time How long to wait for room if Queue is full.
202  * @return True if successful
203  */
204  bool add(T const& item, Time_ms time){
205  return xQueueSendToBack(queueHandle, &item, ms2ticks(time));
206  }
207 #endif
208  /**
209  * @brief Get an item from the Queue.
210  * Gets the first item from the Queue
211  * @param var Variable to place the item
212  * @param time How long to wait for an item to be available.
213  * @return True if an item returned.
214  */
215  bool pop(T& var, TickType_t time = portMAX_DELAY) {
216  return xQueueReceive(queueHandle, &var, time);
217  }
218 #if FREERTOSCPP_USE_CHRONO
219  /**
220  * @brief Get an item from the Queue.
221  * Gets the first item from the Queue
222  * @param var Variable to place the item
223  * @param time How long to wait for an item to be available.
224  * @return True if an item returned.
225  */
226  bool pop(T& var, Time_ms time) {
227  return xQueueReceive(queueHandle, &var, ms2ticks(time));
228  }
229 #endif
230 
231  /**
232  * @brief Look at the first item in the Queue.
233  * Gets the first item from the Queue leaving it there.
234  * @param var Variable to place the item
235  * @param time How long to wait for an item to be available.
236  * @return True if an item returned.
237  */
238  bool peek(T& var, TickType_t time = 0) {
239  return xQueuePeek(queueHandle, &var, time);
240  }
241 #if FREERTOSCPP_USE_CHRONO
242  /**
243  * @brief Look at the first item in the Queue.
244  * Gets the first item from the Queue leaving it there.
245  * @param var Variable to place the item
246  * @param time How long to wait for an item to be available.
247  * @return True if an item returned.
248  */
249  bool peek(T& var, Time_ms time) {
250  return xQueuePeek(queueHandle, &var, ms2ticks(time));
251  }
252 #endif
253 
254  /**
255  * @brief Push an item onto the Queue.
256  * Puts an item onto the Queue so it will be the next item to remove.
257  *
258  * Note: Interrupt service routines should only call _ISR routines.
259  * @param item The item to put on the Queue.
260  * @param waswoken Flag variable to determine if context switch is needed.
261  * @return True if successful
262  */
263  bool push_ISR(T const& item, portBASE_TYPE& waswoken){
264  return xQueueSendToFrontFromISR(queueHandle, &item, &waswoken);
265  }
266 
267  /**
268  * @brief add an item at end of the Queue.
269  * Puts an item onto the Queue so it will be the last item to remove.
270  *
271  * Note: Interrupt service routines should only call _ISR routines.
272  * @param item The item to put on the Queue.
273  * @param waswoken Flag variable to determine if context switch is needed.
274  * @return True if successful
275  */
276  bool add_ISR(T const& item, portBASE_TYPE& waswoken){
277  return xQueueSendToBackFromISR(queueHandle, &item, &waswoken);
278  }
279 
280  /**
281  * @brief Get an item from the Queue.
282  * Gets the first item from the Queue
283  *
284  * Note: Interrupt service routines should only call _ISR routines.
285  * @param var Variable to place the item
286  * @param waswoken Flag variable to determine if context switch is needed.
287  * @return True if an item returned.
288  */
289  bool pop_ISR(T& var, portBASE_TYPE& waswoken) {
290  return xQueueReceiveFromISR(queueHandle, &var, &waswoken);
291  }
292 
293  /**
294  * @brief Look at the first item in the Queue.
295  * Gets the first item from the Queue leaving it there.
296  *
297  * Note: Interrupt service routines should only call _ISR routines.
298  * @param var Variable to place the item
299  * @param waswoken Flag variable to determine if context switch is needed.
300  * @return True if an item returned.
301  */
302  bool peek_ISR(T& var, portBASE_TYPE& waswoken) {
303  return xQueuePeekFromISR(queueHandle, &var);
304  }
305 };
306 
307 /**
308  * @brief Queue Wrapper.
309  *
310  * Note, is a template on the type of object to place on the queue,
311  * which makes the Queue more typesafe.
312  *
313  * @tparam T The type of object to be placed on the queue.
314  * Note also, this type needs to be trivially copyable, and preferably a POD
315  * as the FreeRTOS queue code will copy it with memcpy().
316  * @tparam queuelength The number of elements to reserve space for in the queue.
317  * If 0 (which is the default value) then length will be provided to the constructor dynamically.
318  *
319  * @todo add Overwrite operation
320  * @todo add QueueSet Functionality
321  * @ingroup FreeRTOSCpp
322  */
323 
324 template<class T, unsigned queueLength
325 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
326  = 0
327 #endif
328  > class Queue : public QueueTypeBase<T> {
329 // static_assert(::std::is_pod<T>, "Queues only work with PODs"); ///@todo need to get later version of C++ compile working
330 public:
331  /**
332  * @brief Constructor.
333  * @param name The name to register the Queue with.
334  */
335  Queue(char const* name = 0) :
336  QueueTypeBase<T>(
337 
338 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
339  xQueueCreateStatic(queueLength, sizeof(T), reinterpret_cast<uint8_t*>(&queueStore), &queueBuff)
340 #else
341  xQueueCreate(queueLength, sizeof(T))
342 #endif
343  )
344  {
345 #if configQUEUE_REGISTRY_SIZE > 0
346  if(name)
347  vQueueAddToRegistry(this->queueHandle, name);
348 #endif
349 
350  };
351 private:
352 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
353  StaticQueue_t queueBuff;
354  T queueStore[queueLength];
355 #endif
356 };
357 
358 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
359 
360 template<class T> class Queue<T, 0> : public QueueTypeBase<T> {
361 // static_assert(::std::is_pod<T>, "Queues only work with PODs"); ///@todo need to get later version of C++ compile working
362 public:
363  /**
364  * @brief Constructor.
365  * @param length How many object to make room for in the Queue.
366  * @param name The name to register the Queue with.
367  */
368  Queue(unsigned portBASE_TYPE length, char const* name = 0) :
369  QueueTypeBase<T>(xQueueCreate(length, sizeof(T)))
370  {
371 #if configQUEUE_REGISTRY_SIZE > 0
372  if(name)
373  vQueueAddToRegistry(this->queueHandle, name);
374 #endif
375 
376  };
377 
378 };
379 #endif
380 
381 #if FREERTOSCPP_USE_NAMESPACE
382 } // namespace FreeRTOScpp
383 #endif
384 
385 #endif
bool full_ISR()
Is Queue Full.
Definition: QueueCPP.h:116
unsigned available() const
Return number of spaces available in Queue.
Definition: QueueCPP.h:83
Base Queue Wrapper.
Definition: QueueCPP.h:54
Typed Queue Wrapper.
Definition: QueueCPP.h:159
bool push_ISR(T const &item, portBASE_TYPE &waswoken)
Push an item onto the Queue.
Definition: QueueCPP.h:263
constexpr TickType_t ms2ticks(Time_ms ms)
Definition: FreeRTOScpp.h:81
std::chrono::milliseconds Time_ms
Definition: FreeRTOScpp.h:79
bool add(T const &item, TickType_t time=portMAX_DELAY)
add an item at end of the Queue.
Definition: QueueCPP.h:193
Definition: CallBack.h:63
bool add(T const &item, Time_ms time)
add an item at end of the Queue.
Definition: QueueCPP.h:204
FreeRTOS Wrapper.
virtual ~QueueBase()
Destructor.
Definition: QueueCPP.h:67
bool empty_ISR()
Is Queue Empty.
Definition: QueueCPP.h:125
bool peek_ISR(T &var, portBASE_TYPE &waswoken)
Look at the first item in the Queue.
Definition: QueueCPP.h:302
bool push(T const &item, TickType_t time=portMAX_DELAY)
Push an item onto the Queue.
Definition: QueueCPP.h:171
QueueBase(QueueHandle_t handle_)
Constructor.
Definition: QueueCPP.h:62
bool push(T const &item, Time_ms time)
Push an item onto the Queue.
Definition: QueueCPP.h:182
bool pop(T &var, TickType_t time=portMAX_DELAY)
Get an item from the Queue.
Definition: QueueCPP.h:215
QueueHandle_t queueHandle
Definition: QueueCPP.h:139
bool peek(T &var, TickType_t time=0)
Look at the first item in the Queue.
Definition: QueueCPP.h:238
bool full()
Check if Queue is Full.
Definition: QueueCPP.h:99
void operator=(QueueBase const &)=delete
We are not assignable.
void reset()
Reset the Queue.
Definition: QueueCPP.h:91
unsigned waiting_ISR()
Get number of message waiting.
Definition: QueueCPP.h:134
bool empty()
Check if Queue is Empty.
Definition: QueueCPP.h:107
bool peek(T &var, Time_ms time)
Look at the first item in the Queue.
Definition: QueueCPP.h:249
bool pop(T &var, Time_ms time)
Get an item from the Queue.
Definition: QueueCPP.h:226
QueueTypeBase(QueueHandle_t handle_)
Definition: QueueCPP.h:161
unsigned waiting() const
Get number of items in the Queue.
Definition: QueueCPP.h:75
Queue Wrapper.
Definition: QueueCPP.h:328
bool add_ISR(T const &item, portBASE_TYPE &waswoken)
add an item at end of the Queue.
Definition: QueueCPP.h:276
bool pop_ISR(T &var, portBASE_TYPE &waswoken)
Get an item from the Queue.
Definition: QueueCPP.h:289
Queue(char const *name=0)
Constructor.
Definition: QueueCPP.h:335