/* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.org/license.html */ /** * @file src/gqueue/sys_defs.h * @brief GQUEUE header file. * * @addtogroup GQUEUE * * @brief Module which provides queue management (only internally used) * * @details There are 3 types of queues: * * We need 4 types of queues even though fully synchronous queues support all operations including asynchronous * 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. * @{ */ #ifndef _GQUEUE_H #define _GQUEUE_H #if GFX_USE_GQUEUE || defined(__DOXYGEN__) /** * @brief A queue * @{ */ typedef struct gfxQueueASync { struct gfxQueueASyncItem *head; struct gfxQueueASyncItem *tail; } gfxQueueASync; typedef struct gfxQueueGSync { struct gfxQueueGSyncItem *head; struct gfxQueueGSyncItem *tail; gfxSem sem; } gfxQueueGSync; typedef struct gfxQueueFSync { struct gfxQueueFSyncItem *head; struct gfxQueueFSyncItem *tail; gfxSem sem; } gfxQueueFSync; /* @} */ /** * @brief A queue item * @{ */ typedef struct gfxQueueASyncItem { struct gfxQueueASyncItem *next; } gfxQueueASyncItem; typedef struct gfxQueueGSyncItem { struct gfxQueueGSyncItem *next; } gfxQueueGSyncItem; typedef struct gfxQueueFSyncItem { struct gfxQueueFSyncItem *next; gfxSem sem; } gfxQueueFSyncItem; /* @} */ /*===========================================================================*/ /* Function declarations. */ /*===========================================================================*/ #ifdef __cplusplus extern "C" { #endif /** * @brief Initialise a queue. * * @param[in] pqueue A pointer to the queue * * @note Whilst queues are normally FIFO, a GFX queue also supports push and pop operations. * A pop operation is the same as normal get from the queue but a push places the item * at the head of the queue instead of the tail (as a put would). * * @api * @{ */ void gfxQueueASyncInit(gfxQueueASync *pqueue); void gfxQueueGSyncInit(gfxQueueGSync *pqueue); void gfxQueueFSyncInit(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 * * @param[in] pqueue A pointer to the queue * @param[in] ms The maxmimum time to wait for an item. For ASync queues this parameter is * not specified as TIME_IMMEDIATE is assumed. * * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue); gfxQueueASyncItem *gfxQueueASyncGetI(gfxQueueASync *pqueue); gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms); gfxQueueGSyncItem *gfxQueueGSyncGetI(gfxQueueGSync *pqueue); gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms); /* @} */ /** * @brief Put an item on the end of the queue. * @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE * * @param[in] pqueue A pointer to the queue * @param[in] pitem A pointer to the queue item * @param[in] ms The maxmimum time to wait for an item to be removed from the queue (only for FSync queues) * * @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the * item is removed from the queue. Note that even if the timeout occurs - the item * remains in the queue. * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueASyncPutI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); void gfxQueueGSyncPutI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); /* @} */ /** * @brief Pop an item from the head of the queue (and remove it from the queue). * @details This is exactly the same as the Get operation above. * * @api * @{ */ #define gfxQueueASyncPop(pqueue) gfxQueueASyncGet(pqueue) #define gfxQueueASyncPopI(pqueue) gfxQueueASyncGetI(pqueue) #define gfxQueueGSyncPop(pqueue, ms) gfxQueueGSyncGet(pqueue, ms) #define gfxQueueFSyncPop(pqueue, ms) gfxQueueFSyncGet(pqueue, ms) /* @} */ /** * @brief Push an item into the start of the queue. * @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE * * @param[in] pqueue A pointer to the queue * @param[in] pitem A pointer to the queue item * @param[in] ms The maxmimum time to wait for an item to be popped (only for FSync queues) * * @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the * item is removed from the queue. Note that even if the timeout occurs - the item * remains in the queue. * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueASyncPushI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); /* @} */ /** * @brief Remove an item from the queue. * @note Removes the specified item from the queue where-ever it is in the queue * * @param[in] pqueue A pointer to the queue * @param[in] pitem A pointer to the queue item * * @note If the item isn't in the queue the routine just returns. * @note If a process is waiting on the Put/Push operation for the item, that process * will be signaled. * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueASyncRemoveI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); void gfxQueueGSyncRemoveI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); /* @} */ /** * @brief Is the queue empty? * @return TRUE if the queue is empty * * @param[in] pqueue A pointer to the queue * * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ #define gfxQueueASyncIsEmpty(pqueue) ((pqueue)->head == 0) #define gfxQueueASyncIsEmptyI(pqueue) ((pqueue)->head == 0) #define gfxQueueGSyncIsEmpty(pqueue) ((pqueue)->head == 0) #define gfxQueueGSyncIsEmptyI(pqueue) ((pqueue)->head == 0) #define gfxQueueFSyncIsEmpty(pqueue) ((pqueue)->head == 0) #define gfxQueueFSyncIsEmptyI(pqueue) ((pqueue)->head == 0) /* @} */ /** * @brief Is an item in the queue? * @return TRUE if the item is in the queue? * * @param[in] pqueue A pointer to the queue * @param[in] pitem A pointer to the queue item * * @note This operation may be expensive. * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem); bool_t gfxQueueASyncIsInI(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem); bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem); bool_t gfxQueueGSyncIsInI(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); bool_t gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); /* @} */ /** * @brief Get the first item from the head of the queue but do not remove it from the queue. * @return NULL if no item is available. * * @param[in] pqueue A pointer to the queue * * @note This call does not block. * @note This can be used as the first call to iterate all the elements in the queue. * @note As that item is still on the queue, it should be treated as read-only. It could * also be removed from the queue at any time by another thread (thereby altering the * queue item). * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ #define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head)) #define gfxQueueASyncPeekI(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head)) #define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head)) #define gfxQueueGSyncPeekI(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head)) #define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head)) #define gfxQueueFSyncPeekI(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head)) /* @} */ /** * @brief Get the next item in the queue (but do not remove it from the queue). * @return NULL if no item is available. * * @param[in] pitem The previous item in the queue * * @note This call does not block. * @note This can be used as subsequent calls to iterate all the elements in the queue. * @note As that item is still on the queue, it should be treated as read-only. It could * also be removed from the queue at any time by another thread (thereby altering the * queue item). * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ #define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next)) #define gfxQueueASyncNextI(pitem) ((const gfxQueueASyncItem *)((pitem)->next)) #define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next)) #define gfxQueueGSyncNextI(pitem) ((const gfxQueueGSyncItem *)((pitem)->next)) #define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next)) #define gfxQueueFSyncNextI(pitem) ((const gfxQueueFSyncItem *)((pitem)->next)) /* @} */ #ifdef __cplusplus } #endif #endif /* GFX_USE_GQUEUE */ #endif /* _GQUEUE_H */ /** @} */