WarpTwin
Documentation for WarpTwin models and classes.
Loading...
Searching...
No Matches
Queue.hpp
Go to the documentation of this file.
1/******************************************************************************
2* Copyright (c) ATTX INC 2025. All Rights Reserved.
3*
4* This software and associated documentation (the "Software") are the
5* proprietary and confidential information of ATTX, INC. The Software is
6* furnished under a license agreement between ATTX and the user organization
7* and may be used or copied only in accordance with the terms of the agreement.
8* Refer to 'license/attx_license.adoc' for standard license terms.
9*
10* EXPORT CONTROL NOTICE: THIS SOFTWARE MAY INCLUDE CONTENT CONTROLLED UNDER THE
11* INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) OR THE EXPORT ADMINISTRATION
12* REGULATIONS (EAR99). No part of the Software may be used, reproduced, or
13* transmitted in any form or by any means, for any purpose, without the express
14* written permission of ATTX, INC.
15******************************************************************************/
16/*
17OSAL header file
18
19Author: Alex Reynolds
20*/
21#ifndef DATA_MANAGEMENT_QUEUE_HPP
22#define DATA_MANAGEMENT_QUEUE_HPP
23
24#include <stdint.h>
25
26#include "types.h"
28
29namespace clockwerk {
30
37template <typename T, uint32 L>
38class Queue {
39public:
40 // Can't actually do anything in the constructor
41 Queue() {}
42
46 int16 write(const T& instance);
53 int16 writeBuffer(const T* buffer, uint32 size);
54
58 int16 read(T& instance);
65 int16 readBuffer(T* buffer, uint32 max_vals, uint32& num_vals_read);
66
69 int16 pop();
74 int16 popBuffer(uint32 max_vals, uint32& num_vals_popped);
75
79 int16 peek(T& instance);
84 int16 peekIndex(uint32 index, T& instance);
91 int16 peekBuffer(T* buffer, uint32 max_vals, uint32& num_vals_read);
92
94 void clear();
95
98 uint32 valsAvailable() {return _vals_available;}
99
102 uint32 valsHeld() {return L - _vals_available;}
103protected:
105 uint32 _write_idx = 0;
106
108 uint32 _read_idx = 0;
109
111 uint32 _vals_available = L;
112
115};
116
117template <typename T, uint32 L>
118int16 Queue<T, L>::write(const T& instance) {
119 // Check and return if queue is full
120 if(!_vals_available) {
121 return ERROR_QUEUE_FULL;
122 }
123 // We have vals available. Add to the queue at write ptr and return
124 _buffer[_write_idx] = instance;
126
127 // Increment our write pointer. Note that if it reaches the end of our
128 // buffer we need to wrap back to zero
129 _write_idx++;
130 if(_write_idx == L) {
131 _write_idx = 0;
132 }
133
134 return NO_ERROR;
135}
136
137template <typename T, uint32 L>
138int16 Queue<T, L>::writeBuffer(const T* buffer, uint32 size) {
139 if(buffer == nullptr) {
140 return ERROR_NULLPTR;
141 }
142
143 // Check and return if queue doesn't have enough space
144 if(size > _vals_available) {
145 return ERROR_QUEUE_FULL;
146 }
147 // We have space. Add to the queue in a loop so we can manage the wrap around
148 _vals_available -= size;
149 for(uint32 i = 0; i < size; i++) {
150 // Write value to our buffer
151 _buffer[_write_idx] = buffer[i];
152
153 // And increment our write pointer while managing the wrap
154 _write_idx++;
155 if(_write_idx == L) {
156 _write_idx = 0;
157 }
158 }
159
160 return NO_ERROR;
161}
162
163template <typename T, uint32 L>
164int16 Queue<T, L>::read(T& instance) {
165 // Check if our queue is empty
166 if(_vals_available == L) {
167 return ERROR_QUEUE_EMPTY;
168 }
169 // Queue is not empty. Return value
170 instance = _buffer[_read_idx];
171
172 // And increment our read pointer while managing the wrap
173 _read_idx++;
174 if(_read_idx == L) {
175 _read_idx = 0;
176 }
177
179
180 return NO_ERROR;
181}
182
183template <typename T, uint32 L>
184int16 Queue<T, L>::readBuffer(T* buffer, uint32 max_vals, uint32& num_vals_read) {
185 // Init num_vals_read to 0 in case we exit early
186 num_vals_read = 0;
187
188 if(buffer == nullptr) {
189 return ERROR_NULLPTR;
190 }
191
192 // Check if our queue is empty
193 if(_vals_available == L) {
194 return ERROR_QUEUE_EMPTY;
195 }
196 // Queue is not empty. Identify how many values we can read
197 num_vals_read = L - _vals_available;
198 if(num_vals_read > max_vals) {
199 num_vals_read = max_vals;
200 }
201
202 // And read that many values
203 for(uint32 i = 0; i < num_vals_read; i++) {
204 // Write value to our buffer
205 *(buffer + i) = _buffer[_read_idx];
206
207 // And increment our read pointer while managing the wrap
208 _read_idx++;
209 if(_read_idx == L) {
210 _read_idx = 0;
211 }
212 }
213
214 _vals_available += num_vals_read;
215
216 return NO_ERROR;
217}
218
219template <typename T, uint32 L>
221 // Check if our queue is empty
222 if(_vals_available == L) {
223 return ERROR_QUEUE_EMPTY;
224 }
225
226 // And increment our read pointer while managing the wrap
227 _read_idx++;
228 if(_read_idx == L) {
229 _read_idx = 0;
230 }
231
233
234 return NO_ERROR;
235}
236
237template <typename T, uint32 L>
238int16 Queue<T, L>::popBuffer(uint32 max_vals, uint32& num_vals_popped) {
239 // Init num_vals_popped to 0 in case we exit early
240 num_vals_popped = 0;
241
242 // Check if our queue is empty
243 if(_vals_available == L) {
244 return ERROR_QUEUE_EMPTY;
245 }
246 // Queue is not empty. Identify how many values we can pop
247 num_vals_popped = L - _vals_available;
248 if(num_vals_popped > max_vals) {
249 num_vals_popped = max_vals;
250 }
251
252 // And pop that many values
253 for(uint32 i = 0; i < num_vals_popped; i++) {
254 // And increment our read pointer while managing the wrap
255 _read_idx++;
256 if(_read_idx == L) {
257 _read_idx = 0;
258 }
259 }
260
261 _vals_available += num_vals_popped;
262
263 return NO_ERROR;
264}
265
266template <typename T, uint32 L>
267int16 Queue<T, L>::peek(T& instance) {
268 // Check if our queue is empty
269 if(_vals_available == L) {
270 return ERROR_QUEUE_EMPTY;
271 }
272 // Queue is not empty. Return value but do not change increments
273 instance = _buffer[_read_idx];
274
275 return NO_ERROR;
276}
277
278template <typename T, uint32 L>
279int16 Queue<T, L>::peekIndex(uint32 index, T& instance) {
280 // Check if our queue is empty
281 if(_vals_available == L) {
282 return ERROR_QUEUE_EMPTY;
283 }
284
285 // Check if our index is valid for the queue
286 if(index >= valsHeld()) {
287 return ERROR_INVALID_RANGE;
288 }
289
290 // Loop through values to find index of desired read
291 if(_read_idx + index >= L) {
292 index = _read_idx + index - L;
293 } else {
294 index = _read_idx + index;
295 }
296 instance = _buffer[index];
297
298 return NO_ERROR;
299}
300
301template <typename T, uint32 L>
302int16 Queue<T, L>::peekBuffer(T* buffer, uint32 max_vals, uint32& num_vals_read) {
303 // Init number of values read to 0
304 num_vals_read = 0;
305
306 if(buffer == nullptr) {
307 return ERROR_NULLPTR;
308 }
309
310 // Check if our queue is empty
311 if(_vals_available == L) {
312 return ERROR_QUEUE_EMPTY;
313 }
314 // Queue is not empty. Identify how many values we can read
315 num_vals_read = L - _vals_available;
316 if(num_vals_read > max_vals) {
317 num_vals_read = max_vals;
318 }
319
320 // And read that many values
321 uint32 tmp_idx = _read_idx;
322 for(uint32 i = 0; i < num_vals_read; i++) {
323 // Write value to our buffer
324 *(buffer + i) = _buffer[_read_idx];
325
326 // And increment our read pointer while managing the wrap
327 _read_idx++;
328 if(_read_idx == L) {
329 _read_idx = 0;
330 }
331 }
332 _read_idx = tmp_idx;
333
334 return NO_ERROR;
335}
336
337template <typename T, uint32 L>
339 _write_idx = 0;
340 _read_idx = 0;
341 _vals_available = L;
342}
343
344}
345
346#endif
uint32 valsHeld()
Get the number of values held by the queue.
Definition Queue.hpp:102
int16 peekBuffer(T *buffer, uint32 max_vals, uint32 &num_vals_read)
Read items from the queue without incrementing the read pointer.
Definition Queue.hpp:302
int16 peekIndex(uint32 index, T &instance)
Peek index relative to the read pointer without incrementing the read pointer.
Definition Queue.hpp:279
int16 peek(T &instance)
Read item from the queue without incrementing the read pointer.
Definition Queue.hpp:267
int16 read(T &instance)
Read item from the queue and increment the read pointer.
Definition Queue.hpp:164
int16 readBuffer(T *buffer, uint32 max_vals, uint32 &num_vals_read)
Read items from the queue into buffer and increment read pointer.
Definition Queue.hpp:184
int16 pop()
Function to pop one value from the queue and discard it.
Definition Queue.hpp:220
uint32 _read_idx
Index from which data should be read.
Definition Queue.hpp:108
int16 write(const T &instance)
Write a single data item into the queue.
Definition Queue.hpp:118
void clear()
Clear the queue entirely.
Definition Queue.hpp:338
uint32 _vals_available
Number of values available in the queue.
Definition Queue.hpp:111
int16 popBuffer(uint32 max_vals, uint32 &num_vals_popped)
Function to pop a specified number of values from the queue.
Definition Queue.hpp:238
Queue()
Definition Queue.hpp:41
int16 writeBuffer(const T *buffer, uint32 size)
Write a buffer of data items into the queue.
Definition Queue.hpp:138
T _buffer[L]
Data buffer to hold everything stored in the Queue.
Definition Queue.hpp:114
uint32 valsAvailable()
Get number of spaces in queue.
Definition Queue.hpp:98
uint32 _write_idx
Index to which new data should write.
Definition Queue.hpp:105
#define NO_ERROR
Error code in the case where matrix math executed successfully.
Definition clockwerkerrors.h:34
#define ERROR_NULLPTR
Error code in case of a null pointer.
Definition clockwerkerrors.h:60
#define ERROR_QUEUE_EMPTY
Error in case the queue is empty.
Definition clockwerkerrors.h:198
#define ERROR_QUEUE_FULL
Error in case the queue is full.
Definition clockwerkerrors.h:195
#define ERROR_INVALID_RANGE
Definition clockwerkerrors.h:53
Definition CircularBuffer.hpp:28