µGFX  2.9
version 2.9
gqueue.c
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 #include "../../gfx.h"
9 
10 #if GFX_USE_GQUEUE
11 
12 #if GQUEUE_NEED_BUFFERS
13  static gfxQueueGSync bufferFreeList;
14 #endif
15 
16 void _gqueueInit(void)
17 {
18  #if GQUEUE_NEED_BUFFERS
19  gfxQueueGSyncInit(&bufferFreeList);
20  #endif
21 }
22 
23 void _gqueueDeinit(void)
24 {
25 }
26 
27 #if GQUEUE_NEED_ASYNC
28  void gfxQueueASyncInit(gfxQueueASync *pqueue) {
29  pqueue->head = pqueue->tail = 0;
30  }
31 
32  gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue) {
34 
35  // This is just a shortcut to speed execution
36  if (!pqueue->head)
37  return 0;
38 
39  gfxSystemLock();
40  pi = gfxQueueASyncGetI(pqueue);
42 
43  return pi;
44  }
45  gfxQueueASyncItem *gfxQueueASyncGetI(gfxQueueASync *pqueue) {
47 
48  if ((pi = pqueue->head)) {
49  pqueue->head = pi->next;
50  pi->next = 0;
51  }
52 
53  return pi;
54  }
55 
56  void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
57  gfxSystemLock();
58  gfxQueueASyncPutI(pqueue, pitem);
60  }
61  void gfxQueueASyncPutI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
62  if (!pitem) return; // Safety
63  pitem->next = 0;
64  if (!pqueue->head) {
65  pqueue->head = pqueue->tail = pitem;
66  } else {
67  pqueue->tail->next = pitem;
68  pqueue->tail = pitem;
69  }
70  }
71 
72  void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
73  gfxSystemLock();
74  gfxQueueASyncPushI(pqueue, pitem);
76  }
77  void gfxQueueASyncPushI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
78  if (!pitem) return; // Safety
79  pitem->next = pqueue->head;
80  pqueue->head = pitem;
81  if (!pitem->next)
82  pqueue->tail = pitem;
83  }
84 
85  void gfxQueueASyncInsert(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter) {
86  gfxSystemLock();
87  gfxQueueASyncInsertI(pqueue, pitem, pafter);
89  }
90  void gfxQueueASyncInsertI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter) {
91  if (!pitem) return; // Safety
92 
93  if (pafter && gfxQueueASyncIsInI(pqueue, pafter)) {
94  pitem->next = pafter->next;
95  pafter->next = pitem;
96  if (pqueue->tail == pafter)
97  pqueue->tail = pitem;
98  } else {
99  pitem->next = 0;
100  if (!pqueue->head) {
101  pqueue->head = pqueue->tail = pitem;
102  } else {
103  pqueue->tail->next = pitem;
104  pqueue->tail = pitem;
105  }
106  }
107  }
108 
109  void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
110  gfxSystemLock();
111  gfxQueueASyncRemoveI(pqueue, pitem);
112  gfxSystemUnlock();
113  }
114  void gfxQueueASyncRemoveI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
115  gfxQueueASyncItem *pi;
116 
117  if (!pitem) return; // Safety
118  if (pqueue->head) {
119  if (pqueue->head == pitem) {
120  pqueue->head = pitem->next;
121  pitem->next = 0;
122  } else {
123  for(pi = pqueue->head; pi->next; pi = pi->next) {
124  if (pi->next == pitem) {
125  pi->next = pitem->next;
126  if (pqueue->tail == pitem)
127  pqueue->tail = pi;
128  pitem->next = 0;
129  break;
130  }
131  }
132  }
133  }
134  }
135 
136  gBool gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem) {
137  gBool res;
138 
139  gfxSystemLock();
140  res = gfxQueueASyncIsInI(pqueue, pitem);
141  gfxSystemUnlock();
142 
143  return res;
144  }
145  gBool gfxQueueASyncIsInI(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem) {
146  gfxQueueASyncItem *pi;
147 
148  for(pi = pqueue->head; pi; pi = pi->next) {
149  if (pi == pitem)
150  return gTrue;
151  }
152  return gFalse;
153  }
154 #endif
155 
156 #if GQUEUE_NEED_GSYNC
157  void gfxQueueGSyncInit(gfxQueueGSync *pqueue) {
158  pqueue->head = pqueue->tail = 0;
159  gfxSemInit(&pqueue->sem, 0, gSemMaxCount);
160  }
161  void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue) {
162  pqueue->head = pqueue->tail = 0;
163  gfxSemDestroy(&pqueue->sem);
164  }
165 
166  gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, gDelay ms) {
167  gfxQueueGSyncItem *pi;
168 
169  if (!gfxSemWait(&pqueue->sem, ms))
170  return 0;
171 
172  gfxSystemLock();
173  pi = pqueue->head;
174  pqueue->head = pi->next;
175  pi->next = 0;
176  gfxSystemUnlock();
177 
178  return pi;
179  }
180  gfxQueueGSyncItem *gfxQueueGSyncGetI(gfxQueueGSync *pqueue) {
181  gfxQueueGSyncItem *pi;
182 
183  if (!gfxSemWaitI(&pqueue->sem))
184  return 0;
185 
186  pi = pqueue->head;
187  pqueue->head = pi->next;
188  pi->next = 0;
189  return pi;
190  }
191 
192  void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
193  gfxSystemLock();
194  gfxQueueGSyncPutI(pqueue, pitem);
195  gfxSystemUnlock();
196  }
197  void gfxQueueGSyncPutI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
198  if (!pitem) return; // Safety
199  pitem->next = 0;
200  if (!pqueue->head) {
201  pqueue->head = pqueue->tail = pitem;
202  } else {
203  pqueue->tail->next = pitem;
204  pqueue->tail = pitem;
205  }
206  gfxSemSignalI(&pqueue->sem);
207  }
208 
209  void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
210  gfxSystemLock();
211  gfxQueueGSyncPushI(pqueue, pitem);
212  gfxSystemUnlock();
213  }
214  void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
215  if (!pitem) return; // Safety
216  pitem->next = pqueue->head;
217  pqueue->head = pitem;
218  if (!pitem->next)
219  pqueue->tail = pitem;
220  gfxSemSignalI(&pqueue->sem);
221  }
222 
223  void gfxQueueGSyncInsert(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter) {
224  gfxSystemLock();
225  gfxQueueGSyncInsertI(pqueue, pitem, pafter);
226  gfxSystemUnlock();
227  }
228  void gfxQueueGSyncInsertI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter) {
229  if (!pitem) return; // Safety
230 
231  if (pafter && gfxQueueGSyncIsInI(pqueue, pafter)) {
232  pitem->next = pafter->next;
233  pafter->next = pitem;
234  if (pqueue->tail == pafter)
235  pqueue->tail = pitem;
236  } else {
237  pitem->next = 0;
238  if (!pqueue->head) {
239  pqueue->head = pqueue->tail = pitem;
240  } else {
241  pqueue->tail->next = pitem;
242  pqueue->tail = pitem;
243  }
244  }
245  }
246 
247  void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
248  gfxSystemLock();
249  gfxQueueGSyncRemoveI(pqueue, pitem);
250  gfxSystemUnlock();
251  }
252  void gfxQueueGSyncRemoveI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
253  gfxQueueGSyncItem *pi;
254 
255  if (!pitem) return; // Safety
256  if (pqueue->head) {
257  if (pqueue->head == pitem) {
258  pqueue->head = pitem->next;
259  pitem->next = 0;
260  } else {
261  for(pi = pqueue->head; pi->next; pi = pi->next) {
262  if (pi->next == pitem) {
263  pi->next = pitem->next;
264  if (pqueue->tail == pitem)
265  pqueue->tail = pi;
266  pitem->next = 0;
267  break;
268  }
269  }
270  }
271  }
272  }
273 
274  gBool gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem) {
275  gBool res;
276 
277  gfxSystemLock();
278  res = gfxQueueGSyncIsInI(pqueue, pitem);
279  gfxSystemUnlock();
280 
281  return res;
282  }
283  gBool gfxQueueGSyncIsInI(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem) {
284  gfxQueueGSyncItem *pi;
285 
286  for(pi = pqueue->head; pi; pi = pi->next) {
287  if (pi == pitem)
288  return gTrue;
289  }
290  return gFalse;
291  }
292 #endif
293 
294 #if GQUEUE_NEED_FSYNC
295  void gfxQueueFSyncInit(gfxQueueFSync *pqueue) {
296  pqueue->head = pqueue->tail = 0;
297  gfxSemInit(&pqueue->sem, 0, gSemMaxCount);
298  }
299  void gfxQueueFSyncDeinit(gfxQueueFSync *pqueue) {
300  while(gfxQueueFSyncGet(pqueue, gDelayNone));
301  pqueue->head = pqueue->tail = 0;
302  gfxSemDestroy(&pqueue->sem);
303  }
304 
305  gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, gDelay ms) {
306  gfxQueueFSyncItem *pi;
307 
308  if (!gfxSemWait(&pqueue->sem, ms))
309  return 0;
310 
311  gfxSystemLock();
312  pi = pqueue->head;
313  pqueue->head = pi->next;
314  pi->next = 0;
315  gfxSystemUnlock();
316 
317  gfxSemSignal(&pi->sem);
318  gfxSemDestroy(&pi->sem);
319 
320  return pi;
321  }
322 
323  gBool gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gDelay ms) {
324  if (!pitem) return; // Safety
325  gfxSemInit(&pitem->sem, 0, 1);
326  pitem->next = 0;
327 
328  gfxSystemLock();
329  if (!pqueue->head) {
330  pqueue->head = pqueue->tail = pitem;
331  } else {
332  pqueue->tail->next = pitem;
333  pqueue->tail = pitem;
334  }
335  gfxSystemUnlock();
336 
337  gfxSemSignal(&pqueue->sem);
338 
339  return gfxSemWait(&pitem->sem, ms);
340  }
341 
342  gBool gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gDelay ms) {
343  if (!pitem) return; // Safety
344  gfxSemInit(&pitem->sem, 0, 1);
345 
346  gfxSystemLock();
347  pitem->next = pqueue->head;
348  pqueue->head = pitem;
349  if (!pitem->next)
350  pqueue->tail = pitem;
351  gfxSystemUnlock();
352 
353  gfxSemSignal(&pqueue->sem);
354 
355  return gfxSemWait(&pitem->sem, ms);
356  }
357 
358  gBool gfxQueueFSyncInsert(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gfxQueueFSyncItem *pafter, gDelay ms) {
359  if (!pitem) return; // Safety
360  gfxSemInit(&pitem->sem, 0, 1);
361 
362  gfxSystemLock();
363  if (pafter && gfxQueueFSyncIsInI(pqueue, pafter)) {
364  pitem->next = pafter->next;
365  pafter->next = pitem;
366  if (pqueue->tail == pafter)
367  pqueue->tail = pitem;
368  } else {
369  pitem->next = 0;
370  if (!pqueue->head) {
371  pqueue->head = pqueue->tail = pitem;
372  } else {
373  pqueue->tail->next = pitem;
374  pqueue->tail = pitem;
375  }
376  }
377  gfxSystemUnlock();
378 
379  gfxSemSignal(&pqueue->sem);
380 
381  return gfxSemWait(&pitem->sem, ms);
382 
383  }
384 
385  void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) {
386  gfxQueueFSyncItem *pi;
387 
388  if (!pitem) return; // Safety
389  gfxSystemLock();
390  if (pqueue->head) {
391  if (pqueue->head == pitem) {
392  pqueue->head = pitem->next;
393  found:
394  pitem->next = 0;
395  gfxSystemUnlock();
396  gfxSemSignal(&pitem->sem);
397  gfxSemDestroy(&pitem->sem);
398  return;
399  }
400  for(pi = pqueue->head; pi->next; pi = pi->next) {
401  if (pi->next == pitem) {
402  pi->next = pitem->next;
403  if (pqueue->tail == pitem)
404  pqueue->tail = pi;
405  goto found;
406  }
407  }
408  }
409  gfxSystemUnlock();
410  }
411 
412  gBool gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem) {
413  gBool res;
414 
415  gfxSystemLock();
416  res = gfxQueueFSyncIsInI(pqueue, pitem);
417  gfxSystemUnlock();
418 
419  return res;
420  }
421  gBool gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem) {
422  gfxQueueFSyncItem *pi;
423 
424  for(pi = pqueue->head; pi; pi = pi->next) {
425  if (pi == pitem)
426  return gTrue;
427  }
428  return gFalse;
429  }
430 #endif
431 
432 #if GQUEUE_NEED_BUFFERS
433  gBool gfxBufferAlloc(unsigned num, gMemSize size) {
434  GDataBuffer *pd;
435 
436  if (num < 1)
437  return gFalse;
438 
439  // Round up to a multiple of 4 to prevent problems with structure alignment
440  size = (size + 3) & ~0x03;
441 
442  // Allocate the memory
443  if (!(pd = gfxAlloc((size+sizeof(GDataBuffer)) * num)))
444  return gFalse;
445 
446  // Add each of them to our free list
447  for(;num--; pd = (GDataBuffer *)((char *)(pd+1)+size)) {
448  pd->size = size;
449  gfxBufferRelease(pd);
450  }
451 
452  return gTrue;
453  }
454 
455  void gfxBufferRelease(GDataBuffer *pd) { gfxQueueGSyncPut(&bufferFreeList, (gfxQueueGSyncItem *)pd); }
456  void gfxBufferReleaseI(GDataBuffer *pd) { gfxQueueGSyncPutI(&bufferFreeList, (gfxQueueGSyncItem *)pd); }
457  GDataBuffer *gfxBufferGet(gDelay ms) { return (GDataBuffer *)gfxQueueGSyncGet(&bufferFreeList, ms); }
458  GDataBuffer *gfxBufferGetI(void) { return (GDataBuffer *)gfxQueueGSyncGetI(&bufferFreeList); }
459  gBool gfxBufferIsAvailable(void) { return bufferFreeList.head != 0; }
460 
461 #endif
462 
463 
464 #endif /* GFX_USE_GQUEUE */
void gfxSemSignal(gSem *psem)
Signal a semaphore.
gBool gfxSemWait(gSem *psem, gDelay ms)
Wait on a semaphore.
void gfxSystemUnlock(void)
Unlock the operating system previous locked by gfxSystemLock()
void * gfxAlloc(gMemSize sz)
Allocate memory.
void gfxSystemLock(void)
Lock the operating system to protect a sequence of code.
gBool gfxSemWaitI(gSem *psem)
Test if a wait on a semaphore can be satisfied immediately.
void gfxSemDestroy(gSem *psem)
Destroy a Counted Semaphore.
void gfxSemInit(gSem *psem, gSemcount val, gSemcount limit)
Initialise a Counted Semaphore.
void gfxSemSignalI(gSem *psem)
Signal a semaphore.
A Data Buffer Queue.
Definition: gqueue.h:78
A queue.
Definition: gqueue.h:54
A queue item.
Definition: gqueue.h:40