F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
Queue.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title Queue.cpp
3 // \author mstarch, borrowed from @dinkel
4 // \brief Queue implementation for Baremetal devices. No IPC nor thread
5 // safety is implemented as this intended for baremetal devices.
6 // Based on Os/Pthreads/Queue.cpp from @dinkel
7 // ======================================================================
8 #include <FpConfig.hpp>
10 #include <Fw/Types/Assert.hpp>
11 #include <Os/Queue.hpp>
12 
13 #include <new>
14 #include <cstdio>
15 
16 namespace Os {
22  public:
23  BareQueueHandle() : m_init(false) {}
28  bool create(NATIVE_INT_TYPE depth, NATIVE_INT_TYPE msgSize) {
29  bool ret = m_queue.create(depth, msgSize);
30  m_init = ret;
31  return ret;
32  }
33  bool m_init;
36 };
37 
39  m_handle(reinterpret_cast<POINTER_CAST>(nullptr))
40 { }
41 
43  BareQueueHandle* handle = reinterpret_cast<BareQueueHandle*>(this->m_handle);
44  // Queue has already been created... remove it and try again:
45  if (nullptr != handle) {
46  delete handle;
47  handle = nullptr;
48  }
49  //New queue handle, check for success or return error
50  handle = new(std::nothrow) BareQueueHandle;
51  if (nullptr == handle || !handle->create(depth, msgSize)) {
52  return QUEUE_UNINITIALIZED;
53  }
54  //Set handle member variable
55  this->m_handle = reinterpret_cast<POINTER_CAST>(handle);
56  //Register the queue
57  #if FW_QUEUE_REGISTRATION
58  if (this->s_queueRegistry) {
59  this->s_queueRegistry->regQueue(this);
60  }
61  #endif
62  return QUEUE_OK;
63 }
64 
66  // Clean up the queue handle:
67  BareQueueHandle* handle = reinterpret_cast<BareQueueHandle*>(this->m_handle);
68  if (nullptr != handle) {
69  delete handle;
70  }
71  this->m_handle = reinterpret_cast<POINTER_CAST>(nullptr);
72 }
73 
75  FW_ASSERT(handle.m_init);
76  BufferQueue& queue = handle.m_queue;
78  // Push item onto queue:
79  bool success = queue.push(buffer, size, priority);
80  if(!success) {
81  status = Queue::QUEUE_FULL;
82  }
83  return status;
84 }
85 
87  FW_ASSERT(handle.m_init);
88  BufferQueue& queue = handle.m_queue;
89  // If the queue is full, wait until a message is taken off the queue.
90  while(queue.isFull()) {
91  //Forced to assert, as blocking would destroy timely-ness
92  FW_ASSERT(false);
93  }
94  // Push item onto queue:
95  bool success = queue.push(buffer, size, priority);
96  // The only reason push would not succeed is if the queue
97  // was full. Since we waited for the queue to NOT be full
98  // before sending on the queue, the push must have succeeded
99  // unless there was a programming error or a bit flip.
100  FW_ASSERT(success, success);
101  return Queue::QUEUE_OK;
102 }
103 
105  //Check if the handle is null or check the underlying queue is null
106  if ((nullptr == reinterpret_cast<BareQueueHandle*>(this->m_handle)) ||
107  (!reinterpret_cast<BareQueueHandle*>(this->m_handle)->m_init)) {
108  return QUEUE_UNINITIALIZED;
109  }
110  BareQueueHandle& handle = *reinterpret_cast<BareQueueHandle*>(this->m_handle);
111  BufferQueue& queue = handle.m_queue;
112  //Check that the buffer is non-null
113  if (nullptr == buffer) {
114  return QUEUE_EMPTY_BUFFER;
115  }
116  //Fail if there is a size miss-match
117  if (size < 0 || static_cast<NATIVE_UINT_TYPE>(size) > queue.getMsgSize()) {
118  return QUEUE_SIZE_MISMATCH;
119  }
120  //Send to the queue
121  if( QUEUE_NONBLOCKING == block ) {
122  return bareSendNonBlock(handle, buffer, size, priority);
123  }
124 
125  return bareSendBlock(handle, buffer, size, priority);
126 }
127 
129  FW_ASSERT(handle.m_init);
130  BufferQueue& queue = handle.m_queue;
131  NATIVE_UINT_TYPE size = static_cast<NATIVE_UINT_TYPE>(capacity);
132  NATIVE_INT_TYPE pri = 0;
134  // Get an item off of the queue:
135  bool success = queue.pop(buffer, size, pri);
136  if(success) {
137  // Pop worked - set the return size and priority:
138  actualSize = static_cast<NATIVE_INT_TYPE>(size);
139  priority = pri;
140  }
141  else {
142  actualSize = 0;
143  if( size > static_cast<NATIVE_UINT_TYPE>(capacity) ) {
144  // The buffer capacity was too small!
146  }
147  else if( size == 0 ) {
148  // The queue is empty:
149  status = Queue::QUEUE_NO_MORE_MSGS;
150  }
151  else {
152  // If this happens, a programming error or bit flip occurred:
153  FW_ASSERT(0);
154  }
155  }
156  return status;
157 }
158 
160  FW_ASSERT(handle.m_init);
161  BufferQueue& queue = handle.m_queue;
162  NATIVE_UINT_TYPE size = static_cast<NATIVE_UINT_TYPE>(capacity);
163  NATIVE_INT_TYPE pri = 0;
165  // If the queue is full, wait until a message is taken off the queue.
166  while(queue.isEmpty()) {
167  //Forced to assert, as blocking would destroy timely-ness
168  FW_ASSERT(false);
169  }
170  // Get an item off of the queue:
171  bool success = queue.pop(buffer, size, pri);
172  if(success) {
173  // Pop worked - set the return size and priority:
174  actualSize = static_cast<NATIVE_INT_TYPE>(size);
175  priority = pri;
176  }
177  else {
178  actualSize = 0;
179  if( size > (static_cast<NATIVE_UINT_TYPE>(capacity)) ) {
180  // The buffer capacity was too small!
182  }
183  else {
184  // If this happens, a programming error or bit flip occurred:
185  // The only reason a pop should fail is if the user's buffer
186  // was too small.
187  FW_ASSERT(0);
188  }
189  }
190  return status;
191 }
192 
194  //Check if the handle is null or check the underlying queue is null
195  if ((nullptr == reinterpret_cast<BareQueueHandle*>(this->m_handle)) ||
196  (!reinterpret_cast<BareQueueHandle*>(this->m_handle)->m_init)) {
197  return QUEUE_UNINITIALIZED;
198  }
199  BareQueueHandle& handle = *reinterpret_cast<BareQueueHandle*>(this->m_handle);
200  //Check the buffer can hold the out-going message
201  if (capacity < this->getMsgSize()) {
202  return QUEUE_SIZE_MISMATCH;
203  }
204  //Receive either non-blocking or blocking
205  if(QUEUE_NONBLOCKING == block) {
206  return bareReceiveNonBlock(handle, buffer, capacity, actualSize, priority);
207  }
208  return bareReceiveBlock(handle, buffer, capacity, actualSize, priority);
209 }
210 
212  //Check if the handle is null or check the underlying queue is null
213  if ((nullptr == reinterpret_cast<BareQueueHandle*>(this->m_handle)) ||
214  (!reinterpret_cast<BareQueueHandle*>(this->m_handle)->m_init)) {
215  return 0;
216  }
217  BareQueueHandle& handle = *reinterpret_cast<BareQueueHandle*>(this->m_handle);
218  BufferQueue& queue = handle.m_queue;
219  return queue.getCount();
220 }
221 
223  //Check if the handle is null or check the underlying queue is null
224  if ((nullptr == reinterpret_cast<BareQueueHandle*>(this->m_handle)) ||
225  (!reinterpret_cast<BareQueueHandle*>(this->m_handle)->m_init)) {
226  return 0;
227  }
228  BareQueueHandle& handle = *reinterpret_cast<BareQueueHandle*>(this->m_handle);
229  BufferQueue& queue = handle.m_queue;
230  return queue.getMaxCount();
231 }
232 
234  //Check if the handle is null or check the underlying queue is null
235  if ((nullptr == reinterpret_cast<BareQueueHandle*>(this->m_handle)) ||
236  (!reinterpret_cast<BareQueueHandle*>(this->m_handle)->m_init)) {
237  return 0;
238  }
239  BareQueueHandle& handle = *reinterpret_cast<BareQueueHandle*>(this->m_handle);
240  BufferQueue& queue = handle.m_queue;
241  return queue.getDepth();
242  }
243 
245  //Check if the handle is null or check the underlying queue is null
246  if ((nullptr == reinterpret_cast<BareQueueHandle*>(this->m_handle)) ||
247  (!reinterpret_cast<BareQueueHandle*>(this->m_handle)->m_init)) {
248  return 0;
249  }
250  BareQueueHandle& handle = *reinterpret_cast<BareQueueHandle*>(this->m_handle);
251  BufferQueue& queue = handle.m_queue;
252  return queue.getMsgSize();
253 }
254 }//Namespace Os
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformPointerCastType POINTER_CAST
Definition: BasicTypes.h:53
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
C++-compatible configuration header for fprime configuration.
bool m_init
Actual queue used to store.
Definition: Queue.cpp:33
BufferQueue m_queue
Definition: Queue.cpp:35
bool create(NATIVE_INT_TYPE depth, NATIVE_INT_TYPE msgSize)
Definition: Queue.cpp:28
A generic buffer queue data structure.
Definition: BufferQueue.hpp:26
bool create(NATIVE_UINT_TYPE depth, NATIVE_UINT_TYPE msgSize)
BufferQueue creation.
NATIVE_UINT_TYPE getCount()
Get the current number of items on the queue.
NATIVE_UINT_TYPE getMsgSize()
Get the maximum message size.
bool pop(U8 *buffer, NATIVE_UINT_TYPE &size, NATIVE_INT_TYPE &priority)
pop an item off the queue
NATIVE_UINT_TYPE getDepth()
Get the queue depths.
bool isEmpty()
check if the queue is empty
bool push(const U8 *buffer, NATIVE_UINT_TYPE size, NATIVE_INT_TYPE priority)
push an item onto the queue
bool isFull()
check if the queue is full
NATIVE_UINT_TYPE getMaxCount()
Get the maximum number of items seen on the queue.
NATIVE_INT_TYPE getMsgSize() const
get the message size (maximum message size queue can hold)
Definition: Queue.cpp:244
QueueStatus
Definition: Queue.hpp:27
@ QUEUE_SIZE_MISMATCH
attempted to send or receive with buffer too large, too small
Definition: Queue.hpp:31
@ QUEUE_UNINITIALIZED
Queue wasn't initialized successfully.
Definition: Queue.hpp:30
@ QUEUE_NO_MORE_MSGS
If non-blocking, all the messages have been drained.
Definition: Queue.hpp:29
@ QUEUE_EMPTY_BUFFER
supplied buffer is empty
Definition: Queue.hpp:35
@ QUEUE_OK
message sent/received okay
Definition: Queue.hpp:28
@ QUEUE_FULL
queue was full when attempting to send a message
Definition: Queue.hpp:36
QueueStatus send(const Fw::SerializeBufferBase &buffer, NATIVE_INT_TYPE priority, QueueBlocking block)
send a message
Definition: QueueCommon.cpp:13
Queue()
Definition: Queue.cpp:38
QueueStatus createInternal(const Fw::StringBase &name, NATIVE_INT_TYPE depth, NATIVE_INT_TYPE msgSize)
create a message queue
Definition: Queue.cpp:42
QueueStatus receive(Fw::SerializeBufferBase &buffer, NATIVE_INT_TYPE &priority, QueueBlocking block)
receive a message
Definition: QueueCommon.cpp:22
NATIVE_INT_TYPE getQueueSize() const
get the queue depth (maximum number of messages queue can hold)
Definition: Queue.cpp:233
NATIVE_INT_TYPE getMaxMsgs() const
get the maximum number of messages (high watermark)
Definition: Queue.cpp:222
QueueBlocking
Definition: Queue.hpp:40
@ QUEUE_NONBLOCKING
Queue receive always returns even if there is no message.
Definition: Queue.hpp:42
NATIVE_INT_TYPE getNumMsgs() const
get the number of messages in the queue
Definition: Queue.cpp:211
virtual ~Queue()
Definition: Queue.cpp:65
POINTER_CAST m_handle
handle for implementation specific queue
Definition: Queue.hpp:75
Queue::QueueStatus bareReceiveBlock(BareQueueHandle &handle, U8 *buffer, NATIVE_INT_TYPE capacity, NATIVE_INT_TYPE &actualSize, NATIVE_INT_TYPE &priority)
Definition: Queue.cpp:159
Queue::QueueStatus bareSendNonBlock(BareQueueHandle &handle, const U8 *buffer, NATIVE_INT_TYPE size, NATIVE_INT_TYPE priority)
Definition: Queue.cpp:74
Queue::QueueStatus bareSendBlock(BareQueueHandle &handle, const U8 *buffer, NATIVE_INT_TYPE size, NATIVE_INT_TYPE priority)
Definition: Queue.cpp:86
Queue::QueueStatus bareReceiveNonBlock(BareQueueHandle &handle, U8 *buffer, NATIVE_INT_TYPE capacity, NATIVE_INT_TYPE &actualSize, NATIVE_INT_TYPE &priority)
Definition: Queue.cpp:128