CAlgQueue.h
#ifndef _C_ALG_QUEUE_H_
#define _C_ALG_QUEUE_H_
#include <stdlib.h>
#include <string.h>
#include "CAlgCommon.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned int head;
unsigned int tail;
unsigned int max_count; //q_arrary[0...max_count-1], queue can only hold max-1 items
unsigned int elem_size;
#ifdef WIN32
#pragma warning(disable:4200)
#endif
unsigned char q_arrary[0];
#ifdef WIN32
#pragma warning(default:4200)
#endif
}CAlgQueue;
static inline unsigned int CAlgQueue_MemSize(unsigned int elem_size, unsigned int max_count)
{
return sizeof(CAlgQueue) + elem_size * max_count;
}
static inline void CAlgQueue_Reset(CAlgQueue* q, unsigned int elem_size, unsigned int max_count)
{
q->head = q->tail = 0;
q->max_count = max_count;
q->elem_size = elem_size;
}
static inline unsigned int CAlgQueue_Count(CAlgQueue* q)
{
return (q->head + q->max_count - q->tail)%(q->max_count);
}
static inline int CAlgQueue_IsFull(CAlgQueue* q)
{
return ((q->head + 1) % (q->max_count)) == q->tail;
}
static inline int CAlgQueue_IsEmpty(CAlgQueue* q)
{
return q->head == q->tail;
}
static inline int CAlgQueue_Push(CAlgQueue* q, void* e)
{
unsigned int rc = -1;
if(CAlgQueue_IsFull(q)) return rc;
rc = q->head;
memcpy(& q->q_arrary[q->elem_size * rc], e, q->elem_size);
q->head = (rc + 1) % q->max_count;
return rc ;
}
static inline int CAlgQueue_Pop(CAlgQueue* q, void* e)
{
unsigned int rc = -1;
if(CAlgQueue_IsEmpty(q)) return rc;
rc = q->tail;
memcpy(e, & q->q_arrary[q->elem_size * rc], q->elem_size);
q->tail = (rc + 1) % q->max_count;
return rc ;
}
#ifdef __cplusplus
}
#endif
#endif
//end of file
单元测试:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "CAlgQueue.h"
#define MAX_QUEUE_NODE_ELEM 10000000
typedef struct {
int a;
int b;
}CAlgQueueData;
static CAlgQueue* g_AlgQueue;
void TestAlgQueue_Init()
{
g_AlgQueue = (CAlgQueue*)malloc(CAlgQueue_MemSize(sizeof(CAlgQueueData),MAX_QUEUE_NODE_ELEM));
CAlgQueue_Reset(g_AlgQueue,sizeof(CAlgQueueData),MAX_QUEUE_NODE_ELEM);
}
void TestAlgQueue_Free()
{
free(g_AlgQueue);
}
void TestAlgQueue_Push_Pop()
{
int i;
CAlgQueueData qd ;
//queue is empty
assert(CAlgQueue_IsEmpty(g_AlgQueue));
assert(!CAlgQueue_IsFull(g_AlgQueue));
assert(CAlgQueue_Pop(g_AlgQueue, &qd) == -1);
//////////////////////////////////////////////////////////////////////////
//test queue push to full
for(i=0; i<MAX_QUEUE_NODE_ELEM-1; i++)
{
qd.a = 1000+i;
qd.b = 1001+i;
assert(!CAlgQueue_IsFull(g_AlgQueue));
assert(i == CAlgQueue_Push(g_AlgQueue, (void*)&qd));
assert(!CAlgQueue_IsEmpty(g_AlgQueue));
assert(CAlgQueue_Count(g_AlgQueue) == i+1);
}
//queue is full
assert(CAlgQueue_Count(g_AlgQueue) == MAX_QUEUE_NODE_ELEM-1);
assert(CAlgQueue_IsFull(g_AlgQueue));
//queue is full and push return -1
assert(-1 == CAlgQueue_Push(g_AlgQueue, &qd));
assert(g_AlgQueue->head == MAX_QUEUE_NODE_ELEM-1);
assert(g_AlgQueue->tail == 0);
//////////////////////////////////////////////////////////////////////////
//test queue pop to empty
i=0;
while(CAlgQueue_Pop(g_AlgQueue, &qd) != -1)
{
assert(qd.a == 1000+i);
assert(qd.b == 1001+i);
i++;
}
assert(i == MAX_QUEUE_NODE_ELEM-1);
assert(CAlgQueue_Count(g_AlgQueue) == 0u);
assert(!CAlgQueue_IsFull(g_AlgQueue));
assert(CAlgQueue_IsEmpty(g_AlgQueue));
assert(g_AlgQueue->head == MAX_QUEUE_NODE_ELEM-1);
assert(g_AlgQueue->tail == MAX_QUEUE_NODE_ELEM-1);
//////////////////////////////////////////////////////////////////////////
//head and tail are point to MAX_QUEUE_NODE_ELEM - 1
//push and pop another 5 nodes
for(i=0; i<5; i++)
{
qd.a = 500+i;
qd.b = 501+i;
assert(((MAX_QUEUE_NODE_ELEM - 1 + i)%MAX_QUEUE_NODE_ELEM)
== CAlgQueue_Push(g_AlgQueue, (void*)&qd));
}
assert(!CAlgQueue_IsFull(g_AlgQueue));
assert(!CAlgQueue_IsEmpty(g_AlgQueue));
assert(CAlgQueue_Count(g_AlgQueue) == 5u);
assert(g_AlgQueue->head == 4);
i=0;
while(CAlgQueue_Pop(g_AlgQueue, &qd) != -1)
{
assert(qd.a == 500+i);
assert(qd.b == 501+i);
i++;
}
assert(i == 5);
assert(!CAlgQueue_IsFull(g_AlgQueue));
assert(CAlgQueue_IsEmpty(g_AlgQueue));
assert(CAlgQueue_Count(g_AlgQueue) == 0u);
assert(g_AlgQueue->tail == 4);
}
#include <Windows.h>
void TestAlgQueue_Run()
{
SYSTEMTIME st1, st2;
FILETIME ft1, ft2; //100ns
TestAlgQueue_Init();
GetLocalTime(&st1);
TestAlgQueue_Push_Pop();
GetLocalTime(&st2);
SystemTimeToFileTime(&st1, &ft1);
SystemTimeToFileTime(&st2, &ft2);
printf("%s using %u.%03ums to push/pop %d nodes %02u:%02u:%02u.%03u - %02u:%02u:%02u.%03u\n",
__FILE__,
(ft2.dwLowDateTime-ft1.dwLowDateTime)/10000,
(ft2.dwLowDateTime-ft1.dwLowDateTime)/10, MAX_QUEUE_NODE_ELEM,
st1.wHour,st1.wMinute,st1.wSecond,st1.wMilliseconds,
st2.wHour,st2.wMinute,st2.wSecond,st2.wMilliseconds);
TestAlgQueue_Free();
}
//end of file