RT-Thread系列三 邂逅线程链表

214 阅读2分钟

本文已参与 [新人创作礼] 活动,一起开启掘金创作之路。​

线程链表节点就好像是线程控制块里的一个钩子,要把线程插入各种链表中,就是通过这个节点来实现的。链表节点的定义在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;
}

实际上就是依次往后遍历链表,同时增加计数,直到回到起始节点为止。