Matrix653 链表

更新时间:
2024-02-26
下载文档

Matrix653 链表

本节将介绍 Matrix653 链表的使用。

Matrix653 实现了一个双向循环链表,除了在 Matrix653 内部广泛使用外,Matrix653 的 BSP 也可以使用该双向循环链表。本节详细定义在 mx_list.h 中。

链表介绍

双向循环链表的链头和节点都是 MX_LIST_HEAD_TYPEYPE 类型,它可以是一个全局变量,也可以嵌入到其它数据类型当中(如结构体)作为一个成员变量。只要得到节点的地址(节点的指针),就可以使用形如 MX_CONTAINER_OF(pnode, xxx_struct, xxx_member) 的宏来获得容器(如结构体)的地址(容器的指针)。

链表的遍历有三个宏: mx_list_for_each, mx_list_for_each_begin, 和 mx_list_for_each_safe

  • mx_list_for_each_safe安全 的,这里的 安全 指的是链表遍历过程如果有节点删除操作,链表遍历是安全的;
  • mx_list_for_each不安全 的。
  • mx_list_for_each_begin 是从指定节点遍历到链表尾。

可以根据需要选择合适的链表遍历宏。

链表相关数据类型

类型描述
MX_LIST_HEAD_TYPEYPE双向链表节点类型

MX_LIST_HEAD_TYPEYPE

Matrix653 中使用的通用双向链表节点类型为 MX_LIST_HEAD_TYPE,链表节点使用前需要定义,它可以是一个全局变量,也可以嵌入到其它数据类型当中(如结构体)作为一个成员变量。全局链表可以使用宏 MX_LIST_HEAD 进行定义,另外可以使用宏 MX_LIST_HEAD_INIT 对链表进行初始化。

typedef struct _mx_list_head {
    struct _mx_list_head *next;
    struct _mx_list_head *prev;
} MX_LIST_HEAD_TYPEYPE;
参数说明
next指向下一个节点
prev指向前一个节点

链表相关 API

下表展示了链表相关的 API:

API描述
MX_LIST_HEAD定义一个空链表
MX_LIST_HEAD_INIT初始化一个链表为空链表
mx_list_is_empty判断一个链表是否为空
mx_list_is_head判断一个节点是否为链表的表头
mx_list_is_tail判断一个节点是否为链表的末尾
mx_list_is_only_one判断一个节点是否为链表的唯一节点
mx_list_add在链表头插入一个节点
mx_list_add_tail在链表末尾插入一个节点
mx_list_del从链表中移除一个节点
mx_list_del_init从链表中移除一个节点,并更新被移除节点中的 prev、next 指针
mx_list_for_each非安全方式遍历一个链表
mx_list_for_each_begin非安全方式从指定节点遍历一个链表
mx_list_for_each_safe安全方式遍历一个链表
MX_CONTAINER_OF通过链表节点获得容器(结构体)的地址

MX_LIST_HEAD()

  • 描述 定义一个空链表

  • 宏实现

#define MX_LIST_HEAD(name) \
MX_LIST_HEAD_TYPE (name) = { &(name), &(name)}
  • 参数
输入/输出参数描述
[in]name链表变量名
  • 返回值

  • 注意事项

  • 示例

MX_LIST_HEAD_INIT()

  • 描述 初始化链表

  • 宏实现

#define MX_LIST_HEAD_INIT(p) \
    do {                     \
        (p)->next = (p);     \
        (p)->prev = (p);     \
    } while (0)
  • 参数
输入/输出参数描述
[in]p链表的指针
  • 返回值

  • 注意事项

  • 示例

mx_list_is_empty()

  • 描述 判断一个链表是否为空

  • 函数原型

static MX_FORCE_INLINE MX_BOOL mx_list_is_empty(const MX_LIST_HEAD_TYPE *list);
  • 参数
输入/输出参数描述
[in]list链表的指针
  • 返回值 MX_TRUE:链表为空,MX_FALSE:链表不为空

  • 注意事项

  • 示例

mx_list_is_head()

  • 描述 判断一个节点是否为链表的表头

  • 函数原型

static MX_FORCE_INLINE MX_BOOL mx_list_is_head(const MX_LIST_HEAD_TYPE *entry, 
const MX_LIST_HEAD_TYPE *list);
  • 参数
输入/输出参数描述
[in]entry节点
[in]list链表的指针
  • 返回值 MX_TRUE:节点是链表的表头,MX_FALSE:节点不是链表的表头

  • 注意事项

  • 示例

mx_list_is_tail()

  • 描述 判断一个节点是否为链表的末尾

  • 函数原型

static MX_FORCE_INLINE MX_BOOL mx_list_is_tail(const MX_LIST_HEAD_TYPE *entry, 
const MX_LIST_HEAD_TYPE *list);
  • 参数
输入/输出参数描述
[in]entry节点
[in]list链表指针
  • 返回值 MX_TRUE:节点是链表的末尾,MX_FALSE:节点不是链表的末尾

  • 注意事项

  • 示例

mx_list_is_only_one()

  • 描述 判断一个节点是否为链表的唯一节点

  • 函数原型

static MX_FORCE_INLINE MX_BOOL mx_list_is_only_one(const MX_LIST_HEAD_TYPE *entry, 
const MX_LIST_HEAD_TYPE *list);
  • 参数
输入/输出参数描述
[in]entry节点
[in]list链表的指针
  • 返回值 MX_TRUE:节点是链表的唯一节点,MX_FALSE:节点不是链表的唯一节点

  • 注意事项

  • 示例

mx_list_add()

  • 描述 在链表头插入一个节点

  • 函数原型

static MX_FORCE_INLINE void mx_list_add(MX_LIST_HEAD_TYPE *new_entry, 
MX_LIST_HEAD_TYPE *list);
  • 参数
输入/输出参数描述
[in]new_entry需要插入的节点
[in]list链表的指针
  • 返回值

  • 注意事项

  • 示例

mx_list_add_tail()

  • 描述 在链表末尾插入一个节点

  • 函数原型

static MX_FORCE_INLINE void mx_list_add_tail(MX_LIST_HEAD_TYPE *new_entry, 
MX_LIST_HEAD_TYPE *list);
  • 参数
输入/输出参数描述
[in]new_entry需要插入的节点
[in]list链表的指针
  • 返回值

  • 注意事项

  • 示例

mx_list_del()

  • 描述 从链表中移除一个节点

  • 函数原型

static MX_FORCE_INLINE void mx_list_del(MX_LIST_HEAD_TYPE *const entry);
  • 参数
输入/输出参数描述
[in]entry需要移除的节点
  • 返回值

  • 注意事项 被移除的节点的 prev、next 指针仍指向原节点

  • 示例

mx_list_del_init()

  • 描述 从链表中移除一个节点,并更新被移除节点中的 prev、next 指针

  • 函数原型

static MX_FORCE_INLINE void mx_list_del_init(MX_LIST_HEAD_TYPE *entry);
  • 参数
输入/输出参数描述
[in]entry需要移除的节点
  • 返回值

  • 注意事项 被移除的节点的 prev、next 指针指向 NULL

  • 示例

mx_list_for_each()

  • 描述 非安全方式遍历一个链表

  • 宏实现

#define mx_list_for_each(itervar, list) \
    for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
  • 参数
输入/输出参数描述
[in]itervar临时迭代变量
[in]list链表的指针
  • 返回值

  • 注意事项

  • 示例

mx_list_for_each_begin()

  • 描述 非安全方式从指定节点遍历一个链表

  • 宏实现

#define mx_list_for_each_begin(itervar, begin, list)) \
    for (itervar = (begin); itervar != (list); itervar = itervar->next)
  • 参数
输入/输出参数描述
[in]itervar临时迭代变量
[in]begin从该节点遍历
[in]list链表的指针
  • 返回值

  • 注意事项

  • 示例

mx_list_for_each_safe()

  • 描述 安全方式遍历一个链表

  • 宏实现

#define mx_list_for_each_safe(itervar, save_var, list) \
    for (itervar = (list)->next, save_var = (list)->next->next; \
        itervar != (list); \
        itervar = save_var, save_var = save_var->next)
  • 参数
输入/输出参数描述
[in]itervar临时迭代变量
[in]save_var临时保存变量
[in]list链表的指针
  • 返回值

  • 注意事项

  • 示例

MX_CONTAINER_OF()

  • 描述 通过链表节点获得容器(结构体)的地址

  • 宏实现

#define MX_CONTAINER_OF(entry, type, member) \
    ((type *)(((MX_VIRT_ADDR_TYPE)(entry)) - (MX_VIRT_ADDR_TYPE)(&((type *)MX_NULL)->member)))
  • 参数
输入/输出参数描述
[in]entry链表节点地址
[in]type结构体类型
[in]member结构体中链表节点的变量名
  • 返回值

  • 注意事项

  • 示例

/*
 * XXX struct
 */
typedef struct _MX_XXX_TYPE {
    .....
    MX_LIST_HEAD_TYPE   node;
    .....
} MX_XXX_TYPE;


MX_LIST_HEAD            list;
MX_XXX_TYPE             xxx;
MX_XXX_TYPE             *p;
MX_LIST_HEAD_TYPE       *itervar;

/*
 * Add xxx node to list
 */
mx_list_add(&xxx.node, &list);

/*
 * Traversal list and get XXX struct
 */
mx_list_for_each(itervar, &list) {
    p = MX_CONTAINER_OF(itervar, MX_XXX_TYPE, node);
    ....
}

注意

以上的链表操作都不是线程安全的,如果需要线程安全,请在链表操作的外部加锁(如互斥量)。

文档内容是否对您有所帮助?
有帮助
没帮助