/* "templatizing macros */
#define DEFINE_QUEUE_FUNCTIONS(elem_type)\
void QueueInit_##elem_type##_(tQueue *pQ, elem_type array[], size_t num_elems) {\
pQ->pData = array;\
pQ->ElementsIn = num_elems - 1;\
pQ->iHead = pQ->iTail = 0;\
}\
elem_type QueueRemoveElement_##elem_type##_(tQueue *pQ) {\
elem_type elem;\
elem = ((elem_type*)(pQ->pData))[pQ->iTail];\
pQ->iTail = (pQ->iTail + 1) % pQ->ElementsIn;\
return(elem);\
}\
void QueueAddElement_##elem_type##_(tQueue *pQ, elem_type elem) {\
((elem_type*)(pQ->pData))[pQ->iHead] = elem;\
pQ->iHead = (pQ->iHead + 1) % pQ->ElementsIn;\
}
/* generic queue macro accessor function */
/* init a queue instance */
#define QueueInit(elem_type, t_queue_ptr, elem_array_ptr, num_elems)\
QueueInit_##elem_type##_(t_queue_ptr, elem_array_ptr, num_elems)
/* remove an element from the queue instance */
#define QueueRemoveElement(elem_type, t_queue_ptr)\
QueueRemoveElement_##elem_type##_(t_queue_ptr)
/* add an element to the queue instance */
#define QueueAddElement(elem_type, t_queue_ptr, elem)\
QueueAddElement_##elem_type##_(t_queue_ptr, elem)
/* queue manager struct */
typedef struct {
void *pData;
size_tElementsIn;
size_tiHead;
size_tiTail;
} tQueue;
/* custom data type struct */
typedef struct {
uint8_tData;
uint8_tTag;
} tCustomData;
/* creates the unique functions that operate on tCustomData types */
DEFINE_QUEUE_FUNCTIONS(tCustomData);
/* code */
tCustomData _CustomData;
main()
{
tQueue QCustomData;
tCustomData aCustomData[5];
uint32_t i;
QueueInit(tCustomData, &QCustomData, aCustomData, (sizeof(aCustomData)/sizeof(aCustomData[0])));
for(i = 0; i < (sizeof(aCustomData)/sizeof(aCustomData[0])) - 1; i++)
{
_CustomData.Data = i;
_CustomData.Tag = i;
QueueAddElement(tCustomData, &QCustomData, _CustomData);
}
for(i = 0; i < (sizeof(aCustomData)/sizeof(aCustomData[0])) - 1; i++)
{
_CustomData = QueueRemoveElement(tCustomData, &QCustomData); /* <<< the returned data is correct in "debug"; incorrect in "release" */
}
}
|