QTAILQ队列是QEMU重要的数据结构,例如用来保存QEMU参数等。
QTAILQ_ENTRY
QTAILQ_ENTRY描述前一个和下一个元素的结构体
#define Q_TAILQ_ENTRY(type, qual) \
struct { \
qual type *tqe_next; /* next element */ \
qual type *qual *tqe_prev; /* address of previous next element */\
}
#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,)
- tqe_next是指向下一个元素的指针。
- tqe_prev是一个二级指针,是指针的指针,是前一个元素的tqe_next的地址。
示意图
实例图
QTAILQ_HEAD
QTAILQ_HEAD表示队列头
#define Q_TAILQ_HEAD(name, type, qual) \
struct name { \
qual type *tqh_first; /* first element */ \
qual type *qual *tqh_last; /* addr of last next element */ \
}
#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type,)
- tqh_first是一个一级指针,指向队列中的第一个元素
- tqh_last是一个二级指针,它指向最后一个元素中的tqe_next的地址。
示意图
示例图
TAILQ_INSERT_TAIL
TAILQ_INSERT_TAIL插入元素到队列尾。因为head->tqh_last指向的就是最后一个元素的next->tqe_next指针的地址,所以只要O(1)时间就可以完成插入。
#define QTAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
- elm是指向一个新的队列元素的指针,元素内定义了field QTAILQ_ENTRY结构。
- head是队列头。
- 新元素它的filed.tqe_next没有下一个元素指向,所以设定为NULL。
- 新元素的field.tqe_prev就直接指向(head)->tqh_last,也即原本最后一个元素的filed.tqe_next指针的指针。
- *(head)->tqh_last,也即最后一个元素的field.next指针指向到新元素elm的指针,新元素被放置在队列的最后。
- 队列头指向到新元素(也即新的最后一个元素)的fied.tqe_next指针的地址
示意图
实例图
QTAILQ_INSERT_AFTER
QTAILQ_INSERT_AFTER宏插入到一个元素的后面
#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
情况1,当新元素和原来的某个元素的filed.tqe_next指向同一个元素时,说明要插在后面的元素不是最后一个元素。
情况2,当新元素和原来的某个元素的filed.tqe_next指向空指针NULL,说明要插在队列的最后。
QTAILQ_INSERT_BEFORE
QTAILQ_INSERT_BEFORE把元素elm加到listelm之前
#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
示意图如下
QTAILQ_REMOVE
把elm从队列中移除,要分两种情况。
#define QTAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
情况1,elm元素在队列中间
情况2,elm元素在队列末尾