aboutsummaryrefslogtreecommitdiffstats
path: root/src/gqueue
diff options
context:
space:
mode:
Diffstat (limited to 'src/gqueue')
-rw-r--r--src/gqueue/gqueue.c72
-rw-r--r--src/gqueue/sys_defs.h122
-rw-r--r--src/gqueue/sys_options.h6
-rw-r--r--src/gqueue/sys_rules.h7
4 files changed, 176 insertions, 31 deletions
diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c
index b7ecb032..8540bcea 100644
--- a/src/gqueue/gqueue.c
+++ b/src/gqueue/gqueue.c
@@ -14,6 +14,21 @@
#if GFX_USE_GQUEUE
+#if GQUEUE_NEED_BUFFERS
+ static gfxQueueGSync bufferFreeList;
+#endif
+
+void _gqueueInit(void)
+{
+ #if GQUEUE_NEED_BUFFERS
+ gfxQueueGSyncInit(&bufferFreeList);
+ #endif
+}
+
+void _gqueueDeinit(void)
+{
+}
+
#if GQUEUE_NEED_ASYNC
void gfxQueueASyncInit(gfxQueueASync *pqueue) {
pqueue->head = pqueue->tail = 0;
@@ -49,6 +64,7 @@
gfxSystemUnlock();
}
void gfxQueueASyncPutI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
+ if (!pitem) return; // Safety
pitem->next = 0;
if (!pqueue->head) {
pqueue->head = pqueue->tail = pitem;
@@ -64,6 +80,7 @@
gfxSystemUnlock();
}
void gfxQueueASyncPushI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
+ if (!pitem) return; // Safety
pitem->next = pqueue->head;
pqueue->head = pitem;
if (!pitem->next)
@@ -78,8 +95,7 @@
void gfxQueueASyncRemoveI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) {
gfxQueueASyncItem *pi;
- if (!pitem)
- return;
+ if (!pitem) return; // Safety
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
@@ -123,6 +139,10 @@
pqueue->head = pqueue->tail = 0;
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT);
}
+ void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue) {
+ pqueue->head = pqueue->tail = 0;
+ gfxSemDestroy(&pqueue->sem);
+ }
gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) {
gfxQueueGSyncItem *pi;
@@ -156,6 +176,7 @@
gfxSystemUnlock();
}
void gfxQueueGSyncPutI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
+ if (!pitem) return; // Safety
pitem->next = 0;
if (!pqueue->head) {
pqueue->head = pqueue->tail = pitem;
@@ -172,6 +193,7 @@
gfxSystemUnlock();
}
void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
+ if (!pitem) return; // Safety
pitem->next = pqueue->head;
pqueue->head = pitem;
if (!pitem->next)
@@ -187,8 +209,7 @@
void gfxQueueGSyncRemoveI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) {
gfxQueueGSyncItem *pi;
- if (!pitem)
- return;
+ if (!pitem) return; // Safety
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
@@ -232,6 +253,11 @@
pqueue->head = pqueue->tail = 0;
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT);
}
+ void gfxQueueFSyncDeinit(gfxQueueGSync *pqueue) {
+ while(gfxQueueFSyncGet(pqueue, TIME_IMMEDIATE));
+ pqueue->head = pqueue->tail = 0;
+ gfxSemDestroy(&pqueue->sem);
+ }
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) {
gfxQueueFSyncItem *pi;
@@ -252,6 +278,7 @@
}
bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) {
+ if (!pitem) return; // Safety
gfxSemInit(&pitem->sem, 0, 1);
pitem->next = 0;
@@ -270,6 +297,7 @@
}
bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) {
+ if (!pitem) return; // Safety
gfxSemInit(&pitem->sem, 0, 1);
gfxSystemLock();
@@ -287,9 +315,7 @@
void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) {
gfxQueueFSyncItem *pi;
- if (!pitem)
- return;
-
+ if (!pitem) return; // Safety
gfxSystemLock();
if (pqueue->head) {
if (pqueue->head == pitem) {
@@ -333,4 +359,36 @@
}
#endif
+#if GQUEUE_NEED_BUFFERS
+ bool_t gfxBufferAlloc(unsigned num, size_t size) {
+ GDataBuffer *pd;
+
+ if (num < 1)
+ return FALSE;
+
+ // Round up to a multiple of 4 to prevent problems with structure alignment
+ size = (size + 3) & ~0x03;
+
+ // Allocate the memory
+ if (!(pd = gfxAlloc((size+sizeof(GDataBuffer)) * num)))
+ return FALSE;
+
+ // Add each of them to our free list
+ for(;num--; pd = (GDataBuffer *)((char *)(pd+1)+size)) {
+ pd->size = size;
+ gfxBufferRelease(pd);
+ }
+
+ return TRUE;
+ }
+
+ void gfxBufferRelease(GDataBuffer *pd) { gfxQueueGSyncPut(&bufferFreeList, (gfxQueueGSyncItem *)pd); }
+ void gfxBufferReleaseI(GDataBuffer *pd) { gfxQueueGSyncPutI(&bufferFreeList, (gfxQueueGSyncItem *)pd); }
+ GDataBuffer *gfxBufferGet(delaytime_t ms) { return (GDataBuffer *)gfxQueueGSyncGet(&bufferFreeList, ms); }
+ GDataBuffer *gfxBufferGetI(void) { return (GDataBuffer *)gfxQueueGSyncGetI(&bufferFreeList); }
+ bool_t gfxBufferIsAvailable(void) { return bufferFreeList.head != 0; }
+
+#endif
+
+
#endif /* GFX_USE_GQUEUE */
diff --git a/src/gqueue/sys_defs.h b/src/gqueue/sys_defs.h
index 4351d4ad..b97f2f4d 100644
--- a/src/gqueue/sys_defs.h
+++ b/src/gqueue/sys_defs.h
@@ -23,6 +23,8 @@
* operations because fully synchronous queues have the highest storage requirements. The other queue types are
* optimizations. Efficiency IS important to use (particularly RAM efficiency).
* In practice we only implement ASync, GSync and FSync queues as PSync queues are of dubious value.
+ * <br>
+ * We also define GDataBuffer which is a data buffer that supports being queued.
* @{
*/
@@ -32,45 +34,52 @@
#if GFX_USE_GQUEUE || defined(__DOXYGEN__)
/**
+ * @brief A queue item
+ * @{
+ */
+typedef struct gfxQueueASyncItem {
+ struct gfxQueueASyncItem *next;
+} gfxQueueASyncItem, gfxQueueGSyncItem;
+
+typedef struct gfxQueueFSyncItem {
+ struct gfxQueueFSyncItem *next;
+ gfxSem sem;
+} gfxQueueFSyncItem;
+/* @} */
+
+/**
* @brief A queue
* @{
*/
typedef struct gfxQueueASync {
- struct gfxQueueASyncItem *head;
- struct gfxQueueASyncItem *tail;
+ gfxQueueASyncItem *head;
+ gfxQueueASyncItem *tail;
} gfxQueueASync;
typedef struct gfxQueueGSync {
- struct gfxQueueGSyncItem *head;
- struct gfxQueueGSyncItem *tail;
- gfxSem sem;
+ gfxQueueGSyncItem *head;
+ gfxQueueGSyncItem *tail;
+ gfxSem sem;
} gfxQueueGSync;
typedef struct gfxQueueFSync {
- struct gfxQueueFSyncItem *head;
- struct gfxQueueFSyncItem *tail;
- gfxSem sem;
+ gfxQueueFSyncItem *head;
+ gfxQueueFSyncItem *tail;
+ gfxSem sem;
} gfxQueueFSync;
/* @} */
/**
- * @brief A queue item
- * @{
+ * @brief A Data Buffer Queue
+ * @note This structure is followed immediately by the data itself.
+ * When allocating the buffers for the data put this structure
+ * at the beginning of the buffer.
*/
-typedef struct gfxQueueASyncItem {
- struct gfxQueueASyncItem *next;
-} gfxQueueASyncItem;
-
-typedef struct gfxQueueGSyncItem {
- struct gfxQueueGSyncItem *next;
-} gfxQueueGSyncItem;
-
-typedef struct gfxQueueFSyncItem {
- struct gfxQueueFSyncItem *next;
- gfxSem sem;
-} gfxQueueFSyncItem;
-/* @} */
-
+typedef struct GDataBuffer {
+ gfxQueueGSyncItem next; // @< Used for queueing the buffers
+ size_t size; // @< The size of the buffer area following this structure (in bytes)
+ size_t len; // @< The length of the data in the buffer area (in bytes)
+} GDataBuffer;
/*===========================================================================*/
/* Function declarations. */
@@ -98,6 +107,19 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
+ * @brief De-Initialise a queue.
+ *
+ * @param[in] pqueue A pointer to the queue
+ *
+ * @api
+ * @{
+ */
+#define gfxQueueASyncDeinit(pqueue)
+void gfxQueueGSyncDeinit(gfxQueueGSync *pqueue);
+void gfxQueueFSyncDeinit(gfxQueueFSync *pqueue);
+/* @} */
+
+/**
* @brief Get an item from the head of the queue (and remove it from the queue).
* @return NULL if the timeout expires before an item is available
*
@@ -286,6 +308,58 @@ bool_t gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem)
#define gfxQueueFSyncNextI(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
/* @} */
+/**
+ * @brief Allocate some buffers and put them on the free list
+ * @return TRUE is it succeeded. FALSE on allocation failure.
+ *
+ * @param[in] num The number of buffers to allocate
+ * @param[in] size The size (in bytes) of each buffer
+ *
+ * @api
+ */
+bool_t gfxBufferAlloc(unsigned num, size_t size);
+
+/**
+ * @brief Is there one or more buffers currently available on the free list
+ * @return TRUE if there are buffers in the free list
+ *
+ * @api
+ * @{
+ */
+bool_t gfxBufferIsAvailable(void);
+/* @} */
+
+/**
+ * @brief Get a buffer from the free list
+ * @return A GDataBuffer pointer or NULL if the timeout is exceeded
+ *
+ * @param[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available.
+ *
+ * @api
+ * @{
+ */
+GDataBuffer *gfxBufferGet(delaytime_t ms);
+GDataBuffer *gfxBufferGetI(void);
+/* @} */
+
+/**
+ * @brief Release a buffer back to the free list
+ *
+ * @param[in] pd The buffer to put (back) on the free-list.
+ *
+ * @note This call should be used to return any buffers that were taken from
+ * the free-list once they have been finished with. It can also be used
+ * to put new buffers onto the free-list. Just make sure the "size" field
+ * of the GDataBuffer structure has been filled in first.
+ *
+ * @api
+ * @{
+ */
+void gfxBufferRelease(GDataBuffer *pd);
+void gfxBufferReleaseI(GDataBuffer *pd);
+/* @} */
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gqueue/sys_options.h b/src/gqueue/sys_options.h
index 7c8627ce..169cf116 100644
--- a/src/gqueue/sys_options.h
+++ b/src/gqueue/sys_options.h
@@ -41,6 +41,12 @@
#ifndef GQUEUE_NEED_FSYNC
#define GQUEUE_NEED_FSYNC FALSE
#endif
+ /**
+ * @brief Enable Queue-able Data Buffers
+ */
+ #ifndef GQUEUE_NEED_BUFFERS
+ #define GQUEUE_NEED_BUFFERS FALSE
+ #endif
/**
* @}
*
diff --git a/src/gqueue/sys_rules.h b/src/gqueue/sys_rules.h
index baeb073d..831952d8 100644
--- a/src/gqueue/sys_rules.h
+++ b/src/gqueue/sys_rules.h
@@ -17,6 +17,13 @@
#define _GQUEUE_RULES_H
#if GFX_USE_GQUEUE
+ #if GQUEUE_NEED_BUFFERS && !GQUEUE_NEED_GSYNC
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GQUEUE: GQUEUE_NEED_GSYNC is required if GQUEUE_NEED_BUFFERS is TRUE. It has been turned on for you."
+ #endif
+ #undef GQUEUE_NEED_GSYNC
+ #define GQUEUE_NEED_GSYNC TRUE
+ #endif
#endif
#endif /* _GQUEUE_RULES_H */