直接上源码分析
void vListInitialise( List_t * const pxList )
{
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /* 此时链表中只有一个列表项(结点) */
pxList->xListEnd.xItemValue = portMAX_DELAY; /* 辅助值,用来做升序 */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd )
pxList->uxNumberOfItems = ( UBaseType_t ) 0U; /* 记录列表中节点的数量 */
}
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* 标记此节点属于哪个列表。初始化为NULL */
pxItem->pxContainer = NULL;
}
void vListInsertEnd( List_t * const pxList,
ListItem_t * const pxNewListItem )
{
ListItem_t * const pxIndex = pxList->pxIndex; /* 先拿到这个链表的索引,网上说这个索引指向列表项的头部,但是初始化并没有这个操作 */
pxNewListItem->pxNext = pxIndex; /* 新插入的节点的下一个节点就是这个pxIndex节点 ,新插入的节点指向了末尾节点 */
pxNewListItem->pxPrevious = pxIndex->pxPrevious; /* pxIndex->pxPrevious 指向的是列表的末尾节点,pxNewListItem->pxPrevious 新插入的节点的上一个等于末尾的节点,不知道为什么要这样 */
pxIndex->pxPrevious->pxNext = pxNewListItem; /* pxIndex->pxPrevious->pxNext本来是指向自己,现在指向的是新节点,等于连接起来 */
pxIndex->pxPrevious = pxNewListItem; /* 基本操作了,链接节点 */
pxNewListItem->pxContainer = pxList; /* 标记状态 */
( pxList->uxNumberOfItems )++; /* 节点加1,这里为什么加括号? */
}
void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem )
{
ListItem_t * pxIterator; /* 新建的节点 , 辅助值 */
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; /* 就用这个新的节点值来排序 */
if( xValueOfInsertion == portMAX_DELAY )
{
pxIterator = pxList->xListEnd.pxPrevious; /* 如果要插入的节点的值等于最大值,那就插在End的前一个节点的位置 */
}
else
{
/* 首先pxIterator指向此链表的最后一个节点,判断新插入的节点的值和pxIterator下一个节点的值
此时 pxIterator->pxNext->xItemValue就是首节点的值,(为什么是首节点,因为初始化pxIterator指向了End节点,pxIterator = ( ListItem_t * ) &( pxList->xListEnd ))
如果插入的值大于pxIterator->pxNext->xItemValue(第一次是首节点的值),那么pxIterator=pxIterator->pxNext ,即指向下一个节点继续循环
如果插入的值小于pxIterator->pxNext->xItemValue,那么就说明找到了要插入的地方
那就是新插入的到pxIterator的后面,要插入的节点就是pxIterato和 pxIterato->next之间。
*/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) { }
}
pxNewListItem->pxNext = pxIterator->pxNext; /* 首先把 pxIterator->pxNext 赋值给 pxNewListItem->pxNext,让新列表项指向原本列表中下一个列表项 */
pxNewListItem->pxNext->pxPrevious = pxNewListItem; /* 把 pxNewListItem->pxNext(也就是原本列表中下一个列表项)的 pxNewListItem->pxNext->pxPrevious 成员指向待插入列表项 pxNewListItem,实现双向链表 */
pxNewListItem->pxPrevious = pxIterator; /* 新插入的上一个指向pxIterator,就是上面说的,新的节点插到pxIterator的后面 */
pxIterator->pxNext = pxNewListItem; /* pxIterator->pxNext : 原来的pxIterator节点 (此时只是插入节点,xIterator->pxNext一定要指向pxNewListItem,实现节点的链接)的下一个就是新的节点了 */
pxNewListItem->pxContainer = pxList; /* 老套路了 */
( pxList->uxNumberOfItems )++; /* 列表项个数加1 */
}
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
List_t * const pxList = pxItemToRemove->pxContainer; /* 得到要删除节点链表 */
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; /* 这里就只是改变指针前后链接 */
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
mtCOVERAGE_TEST_DELAY(); /* 这里为什么要存在空函数? */
if( pxList->pxIndex == pxItemToRemove ) /* 很好理解,不做解释 */
{
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
pxItemToRemove->pxContainer = NULL; /* 已经都删除节点了,这个节点的属主链表肯定不存在啊 */
( pxList->uxNumberOfItems )--; /* 老套路了 */
return pxList->uxNumberOfItems; /* 返回这个链表还有几个节点 */
}
// 仍有疑问,希望有人看到能解答一下,在下感激不尽。