qemu QLIST数据结构

简介: queue.h中是qemu使用到的一些基础的数据结构,比如QLIST,QSLIST,QSIMPLEQ,QTAILQ。 本文主要介绍QLIST的数据结构,其它几种数据结构与之类似。

queue.h中是qemu使用到的一些基础的数据结构,比如QLIST,QSLIST,QSIMPLEQ,QTAILQ。


本文主要介绍QLIST的数据结构,其它几种数据结构与之类似。

需要注意entry是嵌入在其他结构体(elm)中使用,QLIST是elm的链表,不是entry的链表。


HEAD

#define QLIST_HEAD(name, type)                                          \
struct name {                                                           \
        struct type *lh_first;  /* first element */                     \
}

lh_first表示list head first


head的静态初始化:

#define QLIST_HEAD_INITIALIZER(head)                                    \
        { NULL }


head的动态初始化:

#define QLIST_INIT(head) do {                                           \
        (head)->lh_first = NULL;                                        \
} while (/*CONSTCOND*/0)



ENTRY

#define QLIST_ENTRY(type)                                               \
struct {                                                                \
        struct type *le_next;   /* next element */                      \
        struct type **le_prev;  /* address of previous next element */  \
}

le_next表示list entry next,le_prev表示list entry prev

注意le_prev,是两个星号,是为了删除elm时的*(elm)->field.le_prev /*等效于之前一个elm的le_next*/ = (elm)->field.le_next;,可以在之后的示意图中详细看看。


elm是包含entry的结构体,比如:

typedef struct elm {
    QLIST_ENTRY(type) field;
    // other fields
} elm;

在head后面插入一个elm:

#define QLIST_INSERT_HEAD(head, elm, field) do {                        \
        if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
                (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
        (head)->lh_first = (elm);                                       \
        (elm)->field.le_prev = &(head)->lh_first;                       \
} while (/*CONSTCOND*/0)


在某个listelm前面或者后面插入elm:

#define QLIST_INSERT_AFTER(listelm, elm, field) do {                    \
        if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
                (listelm)->field.le_next->field.le_prev =               \
                    &(elm)->field.le_next;                              \
        (listelm)->field.le_next = (elm);                               \
        (elm)->field.le_prev = &(listelm)->field.le_next;               \
} while (/*CONSTCOND*/0)

#define QLIST_INSERT_BEFORE(listelm, elm, field) do {                   \
        (elm)->field.le_prev = (listelm)->field.le_prev;                \
        (elm)->field.le_next = (listelm);                               \
        *(listelm)->field.le_prev = (elm);                              \
        (listelm)->field.le_prev = &(elm)->field.le_next;               \
} while (/*CONSTCOND*/0)


删除elm:

#define QLIST_REMOVE(elm, field) do {                                   \
        if ((elm)->field.le_next != NULL)                               \
                (elm)->field.le_next->field.le_prev =                   \
                    (elm)->field.le_prev;                               \
        *(elm)->field.le_prev = (elm)->field.le_next;                   \
} while (/*CONSTCOND*/0)


遍历,safe模式的可以对本elm进行写操作,注意((next_var) = ((var)->field.le_next), 1),让&&后面的条件始终未1,防止next_var为NULL时,少循环一次:

#define QLIST_FOREACH(var, head, field)                                 \
        for ((var) = ((head)->lh_first);                                \
                (var);                                                  \
                (var) = ((var)->field.le_next))

#define QLIST_FOREACH_SAFE(var, head, field, next_var)                  \
        for ((var) = ((head)->lh_first);                                \
                (var) && ((next_var) = ((var)->field.le_next), 1);      \
                (var) = (next_var))


其他操作:

#define QLIST_EMPTY(head)                ((head)->lh_first == NULL)
#define QLIST_FIRST(head)                ((head)->lh_first)
#define QLIST_NEXT(elm, field)           ((elm)->field.le_next)


示意图:




QSLIST是单向链表,QTAILQ的头多了一个指向末尾的指针,不再赘述。


目录
相关文章
|
11月前
|
存储 算法 Linux
打破常规,Linux内核新的数据结构上场maple tree(下)
打破常规,Linux内核新的数据结构上场maple tree
|
存储 JavaScript 前端开发
数据结构之List | 让我们一块来学习数据结构
数据结构之List | 让我们一块来学习数据结构
129 0
|
存储 canal 算法
数据结构之Stack | 让我们一块来学习数据结构
数据结构之Stack | 让我们一块来学习数据结构
51 0
|
5月前
|
存储 算法 Linux
Linux内核代码中常用的数据结构
Linux内核代码中常用的数据结构
95 0
|
11月前
|
存储 算法 容器
数据结构 > 什么是数据结构?
数据结构 > 什么是数据结构?
|
11月前
|
存储 Linux 编译器
打破常规,Linux内核新的数据结构上场maple tree(上)
打破常规,Linux内核新的数据结构上场maple tree
|
存储 算法 安全
【数据结构】C#实现常用数据结构总结
自行整理的C#常见数据结构笔记。
395 0
【数据结构】C#实现常用数据结构总结
|
存储 算法 C语言
数据结构成神篇1-初学数据结构
今天我们开始数据结构的学习,当然,这个有些概念是十分抽象的,只看文章是不一定能懂的,或者说会耗费不少的时间。所以我会持续在B站上面更新讲解视频,都是自己的一些理解和想法。会拿出来和大家一起分享,都是免费的。原创不易,希望大家可以三连支持一下,也希望能给大家带来进步。
87 0
数据结构成神篇1-初学数据结构
|
存储 缓存 Linux
Linux的文件系统的元数据结构是干什么的?底层原理是什么?
Linux的文件系统的元数据结构是干什么的?底层原理是什么?
284 0