µGFX  2.9
version 2.9
gqueue.h
Go to the documentation of this file.
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.io/license.html
6  */
7 
8 /**
9  * @file src/gqueue/gqueue.h
10  * @brief GQUEUE header file.
11  *
12  * @addtogroup GQUEUE
13  *
14  * @brief Module which provides queue management (only internally used)
15  *
16  * @details There are 3 types of queues:
17  * <ul><li><b>Asynchronous Queues (ASync) </b> - Queue operations never block</li>
18  * <li><b>Get Synchronous Queues (GSync) </b> - Queue Get operations block until something is placed in the Queue</li>
19  * <li><b>Put Synchronous Queues (PSync)</b> - Queue Put operations block until the element is removed from the Queue</li>
20  * <li><b>Fully Synchronous Queues (FSync)</b> - Queue GET and Put operations block</li>
21  * </ul>
22  * We need 4 types of queues even though fully synchronous queues support all operations including asynchronous
23  * operations because fully synchronous queues have the highest storage requirements. The other queue types are
24  * optimizations. Efficiency IS important to use (particularly RAM efficiency).
25  * In practice we only implement ASync, GSync and FSync queues as PSync queues are of dubious value.
26  * <br>
27  * We also define GDataBuffer which is a data buffer that supports being queued.
28  * @{
29  */
30 
31 #ifndef _GQUEUE_H
32 #define _GQUEUE_H
33 
34 #if GFX_USE_GQUEUE || defined(__DOXYGEN__)
35 
36 /**
37  * @brief A queue item
38  * @{
39  */
40 typedef struct gfxQueueASyncItem {
41  struct gfxQueueASyncItem *next;
43 
44 typedef struct gfxQueueFSyncItem {
45  struct gfxQueueFSyncItem *next;
46  gSem sem;
47 } gfxQueueFSyncItem;
48 /** @} */
49 
50 /**
51  * @brief A queue
52  * @{
53  */
54 typedef struct gfxQueueASync {
55  gfxQueueASyncItem *head;
56  gfxQueueASyncItem *tail;
58 
59 typedef struct gfxQueueGSync {
60  gfxQueueGSyncItem *head;
61  gfxQueueGSyncItem *tail;
62  gSem sem;
63 } gfxQueueGSync;
64 
65 typedef struct gfxQueueFSync {
66  gfxQueueFSyncItem *head;
67  gfxQueueFSyncItem *tail;
68  gSem sem;
69 } gfxQueueFSync;
70 /** @} */
71 
72 /**
73  * @brief A Data Buffer Queue
74  * @note This structure is followed immediately by the data itself.
75  * When allocating the buffers for the data put this structure
76  * at the beginning of the buffer.
77  */
78 typedef struct GDataBuffer {
79  gfxQueueGSyncItem next; // @< Used for queueing the buffers
80  gMemSize size; // @< The size of the buffer area following this structure (in bytes)
81  gMemSize len; // @< The length of the data in the buffer area (in bytes)
83 
84 /*===========================================================================*/
85 /* Function declarations. */
86 /*===========================================================================*/
87 
88 /**
89  * @name Initialisation functions
90  * @brief Initialise a queue.
91  *
92  * @param[in] pqueue A pointer to the queue
93  *
94  * @note Whilst queues are normally FIFO, a GFX queue also supports push and pop operations.
95  * A pop operation is the same as normal get from the queue but a push places the item
96  * at the head of the queue instead of the tail (as a put would).
97  *
98  * @api
99  * @{
100  */
101 void gfxQueueASyncInit(gfxQueueASync *pqueue);
102 void gfxQueueGSyncInit(gfxQueueGSync *pqueue);
103 void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
104 /** @} */
105 
106 /**
107  * @name Deinitialisation functions
108  * @brief De-Initialise a queue.
109  *
110  * @param[in] pqueue A pointer to the queue
111  *
112  * @api
113  * @{
114  */
115 #define gfxQueueASyncDeinit(pqueue)
116 void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue);
117 void gfxQueueFSyncDeinit(gfxQueueFSync *pqueue);
118 /** @} */
119 
120 /**
121  * @name Get() Functions
122  * @brief Get an item from the head of the queue (and remove it from the queue).
123  * @return NULL if the timeout expires before an item is available
124  *
125  * @param[in] pqueue A pointer to the queue
126  * @param[in] ms The maxmimum time to wait for an item. For ASync queues this parameter is
127  * not specified as gDelayNone is assumed.
128  *
129  * @note The routines ending in "I" are interrupt/system/iclass level routines.
130  *
131  * @api
132  * @{
133  */
134 gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue);
135 gfxQueueASyncItem *gfxQueueASyncGetI(gfxQueueASync *pqueue);
136 gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, gDelay ms);
137 gfxQueueGSyncItem *gfxQueueGSyncGetI(gfxQueueGSync *pqueue);
138 gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, gDelay ms);
139 /** @} */
140 
141 /**
142  * @name Put() Functions
143  * @brief Put an item on the end of the queue.
144  * @return none for ASync and GSync queues; For FSync queues - gFalse on timeout, otherwise gTrue
145  *
146  * @param[in] pqueue A pointer to the queue
147  * @param[in] pitem A pointer to the queue item
148  * @param[in] ms The maxmimum time to wait for an item to be removed from the queue (only for FSync queues)
149  *
150  * @note FSync: Use a delay time of gDelayNone if you don't want to wait until the
151  * item is removed from the queue. Note that even if the timeout occurs - the item
152  * remains in the queue.
153  * @note The routines ending in "I" are interrupt/system/iclass level routines.
154  *
155  * @api
156  * @{
157  */
158 void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
159 void gfxQueueASyncPutI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
160 void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
161 void gfxQueueGSyncPutI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
162 gBool gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gDelay ms);
163 /** @} */
164 
165 /**
166  * @name Pop() Functions
167  * @brief Pop an item from the head of the queue (and remove it from the queue).
168  * @details This is exactly the same as the Get operation above.
169  *
170  * @api
171  * @{
172  */
173 #define gfxQueueASyncPop(pqueue) gfxQueueASyncGet(pqueue)
174 #define gfxQueueASyncPopI(pqueue) gfxQueueASyncGetI(pqueue)
175 #define gfxQueueGSyncPop(pqueue, ms) gfxQueueGSyncGet(pqueue, ms)
176 #define gfxQueueFSyncPop(pqueue, ms) gfxQueueFSyncGet(pqueue, ms)
177 /** @} */
178 
179 /**
180  * @name Push() Functions
181  * @brief Push an item into the start of the queue.
182  * @return none for ASync and GSync queues; For FSync queues - gFalse on timeout, otherwise gTrue
183  *
184  * @param[in] pqueue A pointer to the queue
185  * @param[in] pitem A pointer to the queue item
186  * @param[in] ms The maxmimum time to wait for an item to be popped (only for FSync queues)
187  *
188  * @note FSync: Use a delay time of gDelayNone if you don't want to wait until the
189  * item is removed from the queue. Note that even if the timeout occurs - the item
190  * remains in the queue.
191  * @note The routines ending in "I" are interrupt/system/iclass level routines.
192  *
193  * @api
194  * @{
195  */
196 void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
197 void gfxQueueASyncPushI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
198 void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
199 void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
200 gBool gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gDelay ms);
201 /** @} */
202 
203 /**
204  * @name Insert() Functions
205  * @brief Insert an item on the queue after the specified item.
206  * @return none for ASync and GSync queues; For FSync queues - gFalse on timeout, otherwise gTrue
207  *
208  * @param[in] pqueue A pointer to the queue
209  * @param[in] pitem A pointer to the queue item
210  * @param[in] pafter A pointer to the queue item this new item must be inserted after. If NULL or
211  * pafter can't be found in the queue, it puts the new item at the end of the queue.
212  * @param[in] ms The maxmimum time to wait for an item to be removed from the queue (only for FSync queues)
213  *
214  * @note FSync: Use a delay time of gDelayNone if you don't want to wait until the
215  * item is removed from the queue. Note that even if the timeout occurs - the item
216  * remains in the queue.
217  * @note The routines ending in "I" are interrupt/system/iclass level routines.
218  *
219  * @api
220  * @{
221  */
222 void gfxQueueASyncInsert(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter);
223 void gfxQueueASyncInsertI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter);
224 void gfxQueueGSyncInsert(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter);
225 void gfxQueueGSyncInsertI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter);
226 gBool gfxQueueFSyncInsert(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gfxQueueFSyncItem *pafter, gDelay ms);
227 /** @} */
228 
229 /**
230  * @name Remove() Functions
231  * @brief Remove an item from the queue.
232  * @note Removes the specified item from the queue where-ever it is in the queue
233  *
234  * @param[in] pqueue A pointer to the queue
235  * @param[in] pitem A pointer to the queue item
236  *
237  * @note If the item isn't in the queue the routine just returns.
238  * @note If a process is waiting on the Put/Push operation for the item, that process
239  * will be signaled.
240  * @note The routines ending in "I" are interrupt/system/iclass level routines.
241  *
242  * @api
243  * @{
244  */
245 void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
246 void gfxQueueASyncRemoveI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem);
247 void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
248 void gfxQueueGSyncRemoveI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
249 void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
250 /** @} */
251 
252 /**
253  * @name isEmpty() Functions
254  * @brief Is the queue empty?
255  * @return gTrue if the queue is empty
256  *
257  * @param[in] pqueue A pointer to the queue
258  *
259  * @note The routines ending in "I" are interrupt/system/iclass level routines.
260  *
261  * @api
262  * @{
263  */
264 #define gfxQueueASyncIsEmpty(pqueue) ((pqueue)->head == 0)
265 #define gfxQueueASyncIsEmptyI(pqueue) ((pqueue)->head == 0)
266 #define gfxQueueGSyncIsEmpty(pqueue) ((pqueue)->head == 0)
267 #define gfxQueueGSyncIsEmptyI(pqueue) ((pqueue)->head == 0)
268 #define gfxQueueFSyncIsEmpty(pqueue) ((pqueue)->head == 0)
269 #define gfxQueueFSyncIsEmptyI(pqueue) ((pqueue)->head == 0)
270 /** @} */
271 
272 /**
273  * @name IsInQueue() Functions
274  * @brief Is an item in the queue?
275  * @return gTrue if the item is in the queue?
276  *
277  * @param[in] pqueue A pointer to the queue
278  * @param[in] pitem A pointer to the queue item
279  *
280  * @note This operation may be expensive.
281  * @note The routines ending in "I" are interrupt/system/iclass level routines.
282  *
283  * @api
284  * @{
285  */
286 gBool gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem);
287 gBool gfxQueueASyncIsInI(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem);
288 gBool gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem);
289 gBool gfxQueueGSyncIsInI(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem);
290 gBool gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem);
291 gBool gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem);
292 /** @} */
293 
294 /**
295  * @name Peek() Functions
296  * @brief Get the first item from the head of the queue but do not remove it from the queue.
297  * @return NULL if no item is available.
298  *
299  * @param[in] pqueue A pointer to the queue
300  *
301  * @note This call does not block.
302  * @note This can be used as the first call to iterate all the elements in the queue.
303  * @note As that item is still on the queue, it should be treated as read-only. It could
304  * also be removed from the queue at any time by another thread (thereby altering the
305  * queue item).
306  * @note The routines ending in "I" are interrupt/system/iclass level routines.
307  *
308  * @api
309  * @{
310  */
311 #define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head))
312 #define gfxQueueASyncPeekI(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head))
313 #define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head))
314 #define gfxQueueGSyncPeekI(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head))
315 #define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head))
316 #define gfxQueueFSyncPeekI(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head))
317 /** @} */
318 
319 /**
320  * @name Next() Functions
321  * @brief Get the next item in the queue (but do not remove it from the queue).
322  * @return NULL if no item is available.
323  *
324  * @param[in] pitem The previous item in the queue
325  *
326  * @note This call does not block.
327  * @note This can be used as subsequent calls to iterate all the elements in the queue.
328  * @note As that item is still on the queue, it should be treated as read-only. It could
329  * also be removed from the queue at any time by another thread (thereby altering the
330  * queue item).
331  * @note The routines ending in "I" are interrupt/system/iclass level routines.
332  *
333  * @api
334  * @{
335  */
336 #define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next))
337 #define gfxQueueASyncNextI(pitem) ((const gfxQueueASyncItem *)((pitem)->next))
338 #define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next))
339 #define gfxQueueGSyncNextI(pitem) ((const gfxQueueGSyncItem *)((pitem)->next))
340 #define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
341 #define gfxQueueFSyncNextI(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
342 /** @} */
343 
344 /**
345  * @name BufferAlloc() Functions
346  * @brief Allocate some buffers and put them on the free list
347  * @return gTrue is it succeeded. gFalse on allocation failure.
348  *
349  * @param[in] num The number of buffers to allocate
350  * @param[in] size The size (in bytes) of each buffer
351  *
352  * @api
353  * @{
354  */
355 gBool gfxBufferAlloc(unsigned num, gMemSize size);
356 /** @} */
357 
358 /**
359  * @name BufferIsAvailable() Functions
360  * @brief Is there one or more buffers currently available on the free list
361  * @return gTrue if there are buffers in the free list
362  *
363  * @api
364  * @{
365  */
366 gBool gfxBufferIsAvailable(void);
367 /** @} */
368 
369 /**
370  * @name BufferGet() Functions
371  * @brief Get a buffer from the free list
372  * @return A GDataBuffer pointer or NULL if the timeout is exceeded
373  *
374  * @param[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available.
375  *
376  * @api
377  * @{
378  */
379 GDataBuffer *gfxBufferGet(gDelay ms);
380 GDataBuffer *gfxBufferGetI(void);
381 /** @} */
382 
383 /**
384  * @name BufferRelease() Functions
385  * @brief Release a buffer back to the free list
386  *
387  * @param[in] pd The buffer to put (back) on the free-list.
388  *
389  * @note This call should be used to return any buffers that were taken from
390  * the free-list once they have been finished with. It can also be used
391  * to put new buffers onto the free-list. Just make sure the "size" field
392  * of the GDataBuffer structure has been filled in first.
393  *
394  * @api
395  * @{
396  */
397 void gfxBufferRelease(GDataBuffer *pd);
398 void gfxBufferReleaseI(GDataBuffer *pd);
399 /** @} */
400 
401 #endif /* GFX_USE_GQUEUE */
402 #endif /* _GQUEUE_H */
403 /** @} */
struct gfxQueueASyncItem gfxQueueASyncItem
A queue item.
struct GDataBuffer GDataBuffer
A Data Buffer Queue.
struct gfxQueueASync gfxQueueASync
A queue.
A Data Buffer Queue.
Definition: gqueue.h:78
A semaphore.
Definition: gos.h:104
A queue.
Definition: gqueue.h:54
A queue item.
Definition: gqueue.h:40