ambiq的apollo链表操作

看ambiq的apollo代码觉得这个链表操作比较方便,记录下。
代码思想:
在这里插入图片描述
如上图,定义一个全局变量结构体,结构体中为指向链表的头指针和尾指针,这样比较方便的向头插入(利用pHead)、向尾插入(利用pTail),可以方便的模拟一个fifo,当向非头尾节点即中间的某个节点插入新节点时则从头节点开始遍历,找到此节点(pPrev)把这个新节点插入到pPrev的后面。应用场合是做升序排列,删除是同样道理。

//filename : wsf_queue.h
#ifndef WSF_QUEUE_H
#define WSF_QUEUE_H

#ifdef __cplusplus
extern "C" {
#endif

/**************************************************************************************************
  Macros
**************************************************************************************************/

/*! Initialize a queue 初始化链表头指针*/
#define WSF_QUEUE_INIT(pQueue)          {(pQueue)->pHead = NULL; (pQueue)->pTail = NULL;}

/**************************************************************************************************
  Data Types
**************************************************************************************************/

/*! Queue structure */
typedef struct
{
  void      *pHead;         /*! head of queue */
  void      *pTail;         /*! tail of queue */
} wsfQueue_t;

/**************************************************************************************************
  Function Declarations
**************************************************************************************************/

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueEnq
 *        
 *  \brief  Enqueue an element to the tail of a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element.
 *
 *  \return None.
 */
/*************************************************************************************************/
void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem);

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueDeq
 *        
 *  \brief  Dequeue an element from the head of a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *
 *  \return Pointer to element that has been dequeued or NULL if queue is empty.
 */
/*************************************************************************************************/
void *WsfQueueDeq(wsfQueue_t *pQueue);

/*************************************************************************************************/
/*!
 *  \fn     WsfQueuePush
 *        
 *  \brief  Push an element to the head of a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element.
 *
 *  \return None.
 */
/*************************************************************************************************/
void WsfQueuePush(wsfQueue_t *pQueue, void *pElem);

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueInsert
 *        
 *  \brief  Insert an element into a queue.  This function is typically used when iterating
 *          over a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element to be inserted.
 *  \param  pPrev     Pointer to previous element in the queue before element to be inserted.
 *                    Note:  set pPrev to NULL if pElem is first element in queue.
 *  \return None.
 */
/*************************************************************************************************/
void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev);

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueRemove
 *        
 *  \brief  Remove an element from a queue.  This function is typically used when iterating
 *          over a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element to be removed.
 *  \param  pPrev     Pointer to previous element in the queue before element to be removed.
 *
 *  \return None.
 */
/*************************************************************************************************/
void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev);

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueCount
 *        
 *  \brief  Count the number of elements in a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *
 *  \return Number of elements in queue.
 */
/*************************************************************************************************/
uint16_t WsfQueueCount(wsfQueue_t *pQueue);

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueEmpty
 *        
 *  \brief  Return TRUE if queue is empty.
 *
 *  \param  pQueue    Pointer to queue.
 *
 *  \return TRUE if queue is empty, FALSE otherwise.
 */
/*************************************************************************************************/
bool_t WsfQueueEmpty(wsfQueue_t *pQueue);


#ifdef __cplusplus
};
#endif

#endif /* WSF_QUEUE_H */
//filename :wsf_queue.c
#include "wsf_types.h"
#include "wsf_queue.h"
#include "wsf_assert.h"
#include "wsf_cs.h"

/**************************************************************************************************
  Macros
**************************************************************************************************/

/* Get next queue element */
#define WSF_QUEUE_NEXT(p)               (((wsfQueueElem_t *)(p))->pNext)

/**************************************************************************************************
  Data Types
**************************************************************************************************/

/* Queue element */
typedef struct wsfQueueElem_tag
{
  struct wsfQueueElem_tag *pNext;      /* pointer to next element */
} wsfQueueElem_t;

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueEnq 向尾部插入pElem节点
 *
 *  \brief  Enqueue and element to the tail of a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element.
 *
 *  \return None.
 */
/*************************************************************************************************/
void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem)
{
  WSF_CS_INIT(cs);//临界段初始化

  WSF_ASSERT(pQueue != NULL);
  WSF_ASSERT(pElem != NULL);

  /* initialize next pointer */
  WSF_QUEUE_NEXT(pElem) = NULL;

  /* enter critical section */
  WSF_CS_ENTER(cs);//进入临界段

  /* if queue empty 如果头指针空,则直接向头部插入*/
  if (pQueue->pHead == NULL)
  {
    pQueue->pHead = pElem;
    pQueue->pTail = pElem;
  }
  /* else enqueue element to the tail of queue
     pTail就是尾部元素,所以直接pTail->next指向pElem就插入到尾部
     再更新pTail为新的尾部元素pElem*/
  else
  {
    WSF_QUEUE_NEXT(pQueue->pTail) = pElem;
    pQueue->pTail = pElem;
  }

  /* exit critical section */
  WSF_CS_EXIT(cs);//退出临界段
}

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueDeq,头部弹出一个节点
 *
 *  \brief  Dequeue and element from the head of a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *
 *  \return Pointer to element that has been dequeued or NULL if queue is empty.
 */
/*************************************************************************************************/
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;//pHead就是这个链表的头节点,用pElem保存用于返回

  /* if queue is not empty */
  if (pElem != NULL)
  {
    /* set head to next element in queue */
    pQueue->pHead = WSF_QUEUE_NEXT(pElem);
    //pQueue->pHead指向之前pElem的next即跳过头节点指向第二个节点

    /* check for empty queue 
    这种情况是只有一个节点时,弹出则pHead和pTail都要NULL*/
    if (pQueue->pHead == NULL)
    {
      pQueue->pTail = NULL;
    }
  }

  /* exit critical section */
  WSF_CS_EXIT(cs);

  return pElem;//返回头部弹出节点
}

/*************************************************************************************************/
/*!
 *  \fn     WsfQueuePush 头部插入pElem
 *
 *  \brief  Push and element to the head of a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element.
 *
 *  \return None.
 */
/*************************************************************************************************/
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);

  /* else push element to head of queue 
  让pElem->next指向第一个节点即pQueue->pHead*/
  WSF_QUEUE_NEXT(pElem) = pQueue->pHead;

  /* if queue was empty set tail 
  这种情况是当原本没有节点,此次插入的是作为链表的一地个节点*/
  if (pQueue->pHead == NULL)
  {
    pQueue->pTail = pElem;
  }

  /* set head 
  更新链表的头节点为pElem*/
  pQueue->pHead = pElem;

  /* exit critical section */
  WSF_CS_EXIT(cs);
}

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueInsert,向pPrev节点后插入pElem节点
 *
 *  \brief  Insert an element into a queue.  This function is typically used when iterating
 *          over a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element to be inserted.
 *  \param  pPrev     Pointer to previous element in the queue before element to be inserted.
 *                    Note:  set pPrev to NULL if pElem is first element in queue.
 *  \return None.
 */
/*************************************************************************************************/
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 queue empty or inserting at tail 
  没有节点或者pPrev是尾节点直接向尾部插入*/
  if (pQueue->pHead == NULL || pPrev == pQueue->pTail)
  {
    /* queue as normal */
    WsfQueueEnq(pQueue, pElem);
  }
  /* else if inserting at head 
  如果pPrev == NULL向头部插入*/
  else if (pPrev == NULL)
  {
    /* push to head */
    WsfQueuePush(pQueue, pElem);
  }
  else //pElem插入到pPrev的后面
  {
    /* insert in middle of queue */
    WSF_QUEUE_NEXT(pElem) = WSF_QUEUE_NEXT(pPrev);
    WSF_QUEUE_NEXT(pPrev) = pElem;
  }

  /* exit critical section */
  WSF_CS_EXIT(cs);
}

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueRemove 删除pPrev节点后的pElem节点
 *
 *  \brief  Remove an element from a queue.  This function is typically used when iterating
 *          over a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *  \param  pElem     Pointer to element to be removed.
 *  \param  pPrev     Pointer to previous element in the queue before element to be removed.
 *                    Note:  set pPrev to NULL if pElem is first element in queue.
 *  \return None.
 */
/*************************************************************************************************/
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 first element */
  if (pElem == pQueue->pHead)
  {
    /* remove from head of queue 
    如果pElem是头结点则pHead指向pElem的next*/
    pQueue->pHead = WSF_QUEUE_NEXT(pElem);
  }
  else if (pPrev)
  {
    /* remove from middle of queue, pPrev will never be null 
    pPrev->next 跳过pElem指向pElem->next*/
    WSF_QUEUE_NEXT(pPrev) = WSF_QUEUE_NEXT(pElem);
  }

  /* if last element */
  if (pElem == pQueue->pTail)
  {
    /* update tail 
    如果要删除的pElem是尾节点则要更新pTail节点*/
    pQueue->pTail = pPrev;
  }

  /* exit critical section */
  WSF_CS_EXIT(cs);
}

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueCount,计算链表有多少个节点
 *
 *  \brief  Count the number of elements in a queue.
 *
 *  \param  pQueue    Pointer to queue.
 *
 *  \return Number of elements in queue.
 */
/*************************************************************************************************/
uint16_t WsfQueueCount(wsfQueue_t *pQueue)
{
  wsfQueueElem_t  *pElem;
  uint16_t        count = 0;

  WSF_CS_INIT(cs);

  WSF_ASSERT(pQueue != NULL);

  /* enter critical section */
  WSF_CS_ENTER(cs);

  pElem = pQueue->pHead;

  /* iterate over queue */
  while (pElem != NULL)
  {
    count++;
    pElem = pElem->pNext;
  }

  /* exit critical section */
  WSF_CS_EXIT(cs);

  return count;
}

/*************************************************************************************************/
/*!
 *  \fn     WsfQueueEmpty,判断链表是否有节点
 *
 *  \brief  Return TRUE if queue is empty.
 *
 *  \param  pQueue    Pointer to queue.
 *
 *  \return TRUE if queue is empty, FALSE otherwise.
 */
/*************************************************************************************************/
bool_t WsfQueueEmpty(wsfQueue_t *pQueue)
{
  bool_t      empty;

  WSF_CS_INIT(cs);

  WSF_ASSERT(pQueue != NULL);

  /* enter critical section */
  WSF_CS_ENTER(cs);

  empty = (pQueue->pHead == NULL);

  /* exit critical section */
  WSF_CS_EXIT(cs);

  return empty;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值