本文已参与 [新人创作礼] 活动,一起开启掘金创作之路。
线程链表节点就好像是线程控制块里的一个钩子,要把线程插入各种链表中,就是通过这个节点来实现的。链表节点的定义在rtdef.h中,如下代码所示:
/**
* Double List structure
*/
struct rt_list_node
{
struct rt_list_node *next; /**< point to next node. */
struct rt_list_node *prev; /**< point to prev node. */
};
typedef struct rt_list_node rt_list_t; /**< Type for lists. */
rt_list_t类型的节点中有两个rt_list_t类型的节点指针*next和*prev,分别用来指向链表中的下一个节点和上一个节点。实际上,rt_list_t即struct rt_list_node是一个典型的双(向)链表结构。对于链表节点的操作有以下几种:
- 初始化链表节点
rt_list_t类型的节点的初始化,就是将节点里边的next和prev这两个节点指针指向节点本身。代码在include\rtservice.h中,如下所示:
/**
* @brief initialize a list
*
* @param l list to be initialized
*/
rt_inline void rt_list_init(rt_list_t *l)
{
l->next = l->prev = l;
}
- 后插入
在双向链表指定节点后插入一个节点,具体代码实现仍然在rtservice.h中,如下所示:
/**
* @brief insert a node after a list
*
* @param l list to insert it
* @param n new node to be inserted
*/
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
l->next->prev = n;
n->next = l->next;
l->next = n;
n->prev = l;
}
- 前插入
在双向链表指定节点前插入一个节点,具体代码实现仍然在rtservice.h中,如下所示:
/**
* @brief insert a node before a list
*
* @param n new node to be inserted
* @param l list to insert it
*/
rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
l->prev->next = n;
n->prev = l->prev;
l->prev = n;
n->next = l;
}
- 删除一个节点
从双向链表中删除一个节点,具体代码实现仍然在rtservice.h中,如下所示:
/**
* @brief remove node from list.
* @param n the node to remove from the list.
*/
rt_inline void rt_list_remove(rt_list_t *n)
{
n->next->prev = n->prev;
n->prev->next = n->next;
n->next = n->prev = n;
}
- 获取双向链表中节点的个数(链表的长度)
获取双向链表的长度,具体代码实现仍然在rtservice.h中,如下所示:
/**
* @brief get the list length
* @param l the list to get.
*/
rt_inline unsigned int rt_list_len(const rt_list_t *l)
{
unsigned int len = 0;
const rt_list_t *p = l;
while (p->next != l)
{
p = p->next;
len ++;
}
return len;
}
实际上就是依次往后遍历链表,同时增加计数,直到回到起始节点为止。