QEMU(2) QTAILQ隊列

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元素在隊列末尾

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章