KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
queue.h
Go to the documentation of this file.
1 /*
2  * KM3NeT CLB v2 Firmware
3  *
4  * Copyright 2013 KM3NeT Collaboration
5  *
6  * All Rights Reserved.
7  *
8  * queue.h
9  *
10  * Created on: 2 mei 2013
11  * Author: Vincent van Beveren
12  */
13 
14 #ifndef QUEUE_H_
15 #define QUEUE_H_
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /**
22  * @file
23  *
24  * @ingroup collections
25  *
26  * Queue is created in statically allocated memory. Capacity and size can not
27  * be changed during runtime. Note that the queue definition is broken up in
28  * two parts, the descriptor and the actual queue.
29  *
30  * To simplify creation of the queue use the Q_INIT macro.
31  *
32  */
33 
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include <string.h>
37 
38 
39 
40 
41 /*!
42  * Queue descriptor.
43  *
44  * Describes the memory region, capacity and size.
45  */
46 typedef struct {
47  void * const memoryFirst; //!< first element pointer
48  void * const memoryLast; //!< last element pointer
49  const uint16_t capacity; //!< capacity in entries
50  const uint16_t entrySize; //!< size of an entry
51 } QueueDescr;
52 
53 /*!
54  * \brief Queue state.
55  *
56  * Describes the pointers and the length of the queue.
57  */
58 typedef struct {
59  const QueueDescr * const descr; //!< pointer to the descriptor
60  void * readPtr; //!< read pointer
61  void * writePtr; //!< write pointer
62  uint16_t length; //!< length of the queue
63 } Queue;
64 
65 /*!
66  * \brief Convenience Macro, defines and inits queue.
67  *
68  * Example of how to use it:
69  *
70  * \code
71  * Q_INIT(myQueue, sizeof(MyStruct), 100);
72  *
73  * void receive(MyStruct * myStr) {
74  * qQueue(myQueue, myStr);
75  * }
76  * \endcode
77  *
78  * Must be used outside of any function scope.
79  *
80  * \param NAME Name of the queue pointer.
81  * \param ENTRY_SIZE Size in bytes of one element (use sizeof()).
82  * \param CAPACITY Maximum number of elements in queue.
83  */
84 #define Q_INIT(NAME, ENTRY_SIZE, CAPACITY) \
85  static uint8_t NAME ## Mem[ ( ENTRY_SIZE ) * ( CAPACITY ) ]; \
86  static const QueueDescr NAME ## Descr = { \
87  .memoryFirst = NAME ## Mem, \
88  .memoryLast = NAME ## Mem + ((CAPACITY) - 1) * ( ENTRY_SIZE ), \
89  .capacity = CAPACITY, \
90  .entrySize = ENTRY_SIZE \
91  }; \
92  static Queue NAME = { \
93  .descr = &NAME ## Descr, \
94  .length = 0, \
95  .readPtr = NAME ## Mem, \
96  .writePtr = NAME ## Mem \
97  };
98 
99 
100 /*!
101  * \brief Queue data to the end of the queue in place.
102  *
103  * You can write the element data to the returned pointer, but no not write any further than the
104  * size of the entry.
105  *
106  * \param q The queue.
107  *
108  * \return NULL if the queue is full, else a pointer to the location where you may write
109  * data.
110  */
111 void * qQueueIP(Queue * q);
112 
113 
114 /*!
115  * \brief Queue data to the end of the queue.
116  *
117  * The data is copied into the queue. The Data element must be the size as
118  * defined when creating the queue.
119  *
120  * \param q The queue
121  * \param data The data element to queue
122  * \return True if it as added, false if the
123  * queue was full.
124  */
125 static inline bool qQueue(Queue * q, void * data)
126 {
127  void * target = qQueueIP(q);
128  if (target == NULL) return false;
129  memcpy(target, data, q->descr->entrySize);
130  return true;
131 }
132 
133 /*!
134  * \brief Iterates the queue to check for an element.
135  *
136  * Searching is done by iterating though all elements and performance will drop
137  * with respect to the queue length.
138  *
139  * \param q The queue.
140  * \param data The element to check for.
141  *
142  * \return True if that element was already in the queue, false if not.
143  */
144 bool qContains(Queue * q, void * data);
145 
146 /*!
147  * Dequeue an element from the front of the queue in place.
148  *
149  * A pointer to the data will be given. Take care not to overwrite any more bytes than the size of
150  * the element.
151  *
152  * The data is valid for as long as no elements are written to the queue.
153  *
154  * \param q The queue.
155  *
156  * \return NULL if the queue is empty, else a pointer to the location where you may read
157  * data.
158  */
159 void * qDeQueueIP(Queue * q);
160 
161 
162 /*!
163  * Dequeue an element from the front of the queue.
164  *
165  * The element will be written to the location pointed by data.
166  *
167  * \param q The queue structure
168  * \param data Where to write the dequeued element.
169  *
170  * \return True if an element was dequeued.
171  * False if the queue is empty.
172  */
173 static inline bool qDeQueue(Queue * q, void * data)
174 {
175  void * source = qDeQueueIP(q);
176 
177  if (source == NULL) return false;
178 
179  memcpy(data, source, q->descr->entrySize);
180 
181  return true;
182 }
183 
184 /*!
185  * Delete element from the back for the queue.
186  *
187  * Used for undo-ing if an operation could not be completed.
188  *
189  * \retval true Success
190  * \retval false Queue was empty.
191  */
192 bool qRemoveBack(Queue * q);
193 
194 
195 /*!
196  * \brief Peek at the first element in the queue.
197  *
198  * Returns a pointer to the first element in the queue, without dequeuing it. Note that the pointer
199  * is only valid for as long as the element is in the queue.
200  *
201  * Use together with qNext to create an iterator.
202  *
203  * \see qNext
204  *
205  * \param q The queue structure.
206  *
207  * \param Pointer to the first element in the queue, or NULL if the queue is empty.
208  */
209 static inline void * qFirst(Queue * q)
210 {
211  return q->length == 0 ? NULL : q->readPtr;
212 }
213 
214 /*!
215  * \brief Peek at the next element in the queue.
216  *
217  * Returns a pointer to the next element in the queue, without dequeuing it. Note that the pointer
218  * is only valid for as long as the element is in the queue.
219  *
220  * Can be used together with qFirst to iterate though all elements of a queue. For example:
221  * \code
222  * MyData * d = qFirst(q);
223  * while (d != NULL)
224  * {
225  * doSomething(d);
226  * d = qNext(q, d);
227  * }
228  * \endcode
229  *
230  * \see qFirst
231  *
232  * \param q The queue structure.
233  *
234  * \param Pointer to the net element in the queue, or NULL if you reached the end of the queue.
235  */
236 static inline void * qNext(Queue * q, void * ptr)
237 {
238  ptr = ptr == q->descr->memoryLast ?
239  q->descr->memoryFirst : ptr + q->descr->entrySize;
240  return ptr == q->writePtr ? NULL : ptr;
241 }
242 
243 /*!
244  * Returns whether or not the queue is full.
245  *
246  * \retval true Queue is full
247  * \retval false Queue is not full
248  */
249 static inline bool qFull(Queue * q)
250 {
251  return q->length == q->descr->capacity;
252 }
253 
254 
255 /*!
256  * Resets the queue. After this call the queue is empty.
257  */
258 static inline void qReset(Queue * q)
259 {
260  q->readPtr = q->descr->memoryFirst;
261  q->writePtr = q->descr->memoryFirst;
262  q->length = 0;
263 }
264 
265 #ifdef __cplusplus
266 }
267 #endif
268 
269 #endif /* QUEUE_H_ */
const uint16_t entrySize
size of an entry
Definition: queue.h:50
const uint16_t capacity
capacity in entries
Definition: queue.h:49
static bool qFull(Queue *q)
Returns whether or not the queue is full.
Definition: queue.h:249
static void * qNext(Queue *q, void *ptr)
Peek at the next element in the queue.
Definition: queue.h:236
uint16_t length
length of the queue
Definition: queue.h:62
const QueueDescr *const descr
pointer to the descriptor
Definition: queue.h:59
void * writePtr
write pointer
Definition: queue.h:61
void * readPtr
read pointer
Definition: queue.h:60
Queue state.
Definition: queue.h:58
void *const memoryFirst
first element pointer
Definition: queue.h:47
bool qContains(Queue *q, void *data)
Iterates the queue to check for an element.
Definition: queue.c:55
static void * qFirst(Queue *q)
Peek at the first element in the queue.
Definition: queue.h:209
bool qRemoveBack(Queue *q)
Delete element from the back for the queue.
Definition: queue.c:45
static bool qDeQueue(Queue *q, void *data)
Dequeue an element from the front of the queue.
Definition: queue.h:173
void * qQueueIP(Queue *q)
Queue data to the end of the queue in place.
Definition: queue.c:18
static bool qQueue(Queue *q, void *data)
Queue data to the end of the queue.
Definition: queue.h:125
Queue descriptor.
Definition: queue.h:46
static void qReset(Queue *q)
Resets the queue.
Definition: queue.h:258
void * qDeQueueIP(Queue *q)
Dequeue an element from the front of the queue in place.
Definition: queue.c:33
void *const memoryLast
last element pointer
Definition: queue.h:48