队列
队列的管理使用单向链表结构。个人认为使用双向链表更易于维护。
注意:
- 每个以列队为基础管理的结构都必须将第一个元素设定为列队元件的指针。
- 进行列队操作时都需要关闭任务调度,防止多线程操作的信息同步问题。
队列的管理结构
//队列的管理结构
typedef struct
{
void *pHead; //指向队列的头部节点
void *pTail; //指向队列的尾部节点
} wsfQueue_t;
/* 队列的元件 */
typedef struct wsfQueueElem_tag
{
struct wsfQueueElem_tag *pNext; //保存一个指向下一位置的指针
} wsfQueueElem_t;
队列的初始化
队列的初始化比较简单,仅仅是将头部节点和尾部节点指向NULL
#define WSF_QUEUE_INIT(pQueue) {(pQueue)->pHead = NULL; (pQueue)->pTail = NULL;}
队列尾部增加节点
判断下队列是否为空,为空增加为头部,不为空增加到尾部。仅更改尾部节点。
//向列队的尾部添加一个节点
void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pElem != NULL);
/* 节点的下一个节点指向空 */
WSF_QUEUE_NEXT(pElem) = NULL;
/* enter critical section */
WSF_CS_ENTER(cs);
/* 列队为空,设置列队的的头尾都是刚添加的节点 */
if (pQueue->pHead == NULL)
{
pQueue->pHead = pElem;
pQueue->pTail = pElem;
}
/* 添加到列队的尾部。 */
else
{
WSF_QUEUE_NEXT(pQueue->pTail) = pElem;
pQueue->pTail = pElem;
}
/* exit critical section */
WSF_CS_EXIT(cs);
}
队列头部取出节点
取出头部节点并返回。并判断是否将列队取空了,若空了重新设置尾部节点。
//从列队的头部取出一个节点
void *WsfQueueDeq(wsfQueue_t *pQueue)
{
wsfQueueElem_t *pElem;
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
pElem = pQueue->pHead;
/* 列队不为空时进行操作 */
if (pElem != NULL)
{
/* 将头部节点指向下一个 */
pQueue->pHead = WSF_QUEUE_NEXT(pElem);
/* 判断是都将列队取空了 */
if (pQueue->pHead == NULL)
{
pQueue->pTail = NULL;
}
}
/* exit critical section */
WSF_CS_EXIT(cs);
return pElem;
}
队列头部插入节点
操作类似,不一一赘述,都为单向链表。
void WsfQueuePush(wsfQueue_t *pQueue, void *pElem)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pElem != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
/* 设置节点的下一个节点为头部 */
WSF_QUEUE_NEXT(pElem) = pQueue->pHead;
/* 列队为空的话同时设置尾部指针 */
if (pQueue->pHead == NULL)
{
pQueue->pTail = pElem;
}
/* 重新设置头部节点 */
pQueue->pHead = pElem;
/* exit critical section */
WSF_CS_EXIT(cs);
}
队列中间插入节点
由于是单向链表,因此必须提供前一个节点的指针。
//列队中间插入一个元素。必须提供上一个节点的指针。
void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pElem != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
/* 列队为空或者上一节点为尾部节点时,直接添加到尾部 */
if (pQueue->pHead == NULL || pPrev == pQueue->pTail)
{
/* 常规添加到列队的尾部 */
WsfQueueEnq(pQueue, pElem);
}
/* 判断上一节点是不是头部 */
else if (pPrev == NULL)
{
/* 添加到列队的头部 */
WsfQueuePush(pQueue, pElem);
}
else
{
/* 插入到两个节点中间 */
WSF_QUEUE_NEXT(pElem) = WSF_QUEUE_NEXT(pPrev);
WSF_QUEUE_NEXT(pPrev) = pElem;
}
/* exit critical section */
WSF_CS_EXIT(cs);
}
队列中间删除节点
由于是单向链表,因此必须提供前一个节点的指针。
void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pQueue->pHead != NULL);
WSF_ASSERT(pElem != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
/* 头部节点 */
if (pElem == pQueue->pHead)
{
/* 将头部节点指向当前节点的下一个 */
pQueue->pHead = WSF_QUEUE_NEXT(pElem);
}
else if (pPrev)
{
/* 下一个节点的next指向当前节点的next */
WSF_QUEUE_NEXT(pPrev) = WSF_QUEUE_NEXT(pElem);
}
/* 如果是尾部节点 */
if (pElem == pQueue->pTail)
{
/* 尾部节点更新为上一个节点 */
pQueue->pTail = pPrev;
}
/* exit critical section */
WSF_CS_EXIT(cs);
}