tail queue代码阅读

tail queue是bdb中用的最多的数据结构. 定义在 src/dbinc/queue.h:
注: TRACEBUF,QMD_TRACE_HEAD等是为了 queue代码的debug, 这里移除出去.

数据结构
========

```
// type 即为 用户定义的 类型. 比如 db.h, 
// struct __db_txn { 
//      * TAILQ_HEAD(__kids, __db_txn) kids;
//     */
//    struct __kids { type 即为 _db_txn. 问题:  用什么不直接用 TAILQ_HEAD(__kids, __db_txn) kids? 
//        struct __db_txn *tqh_first;
//        struct __db_txn **tqh_last;
//    } kids;

#define    TAILQ_HEAD(name, type)        \  // 理解为 "头结点"
struct name {                                \
    struct type *tqh_first;    /* first element */        \ // 此为具体的元素, 如 __db_txn
    struct type **tqh_last;    /* addr of last next element */    \ // "最后一个元素的tqe_next" 的地址
}

#define    TAILQ_ENTRY(type)                        \
struct {                                \
    struct type *tqe_next;    /* next element */            \ // 此为具体的元素, 如 __db_txn
    struct type **tqe_prev;    /* address of previous next element */ \ "前一个元素的tqe_next" 的地址
}
```

方法定义
=========

```
#define    TAILQ_EMPTY(head)    ((head)->tqh_first == NULL)
#define    TAILQ_FIRST(head)    ((head)->tqh_first)

/**
 * 这里做了一个trick. 看TAILQ_HEAD 和TAILQ_ENTRY的定义, 只有 TAILQ_HEAD给了struct name. 
 * 所以 强制转为 `(struct headname *)`, (而不是 `(struct entryname *)`). 但是 TAILQ_HEAD 和
 * TAILQ_ENTRY 的定义是相同的, `(head)->tqh_last)` 为 最后一个元素的 tqe_next 的地址, 
 * 所以如果有 `struct entryname`的话,  即为 此 `struct entryname` 的地址. 
 * `(((struct headname *)((head)->tqh_last))->tqh_last)` 即为:
 * `(((struct entryname *)((head)->tqh_last))->tqe_prev)`. 倒数第二个元素的  tqe_next.
 * TAILQ_PREV 的定义也是这么理解.
 */
#define    TAILQ_LAST(head, headname)    \  
    (*(((struct headname *)((head)->tqh_last))->tqh_last))

#define    TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)

/**
 * field 为type中, queue entry的field. 其 `(elm)->field.tqe_prev)` 为 前一个元素的 tqe_next 的地址, 
 * 所以如果有 `struct entryname`的话,  即为 前一个元素的 queue entry field 的地址.  
 * `(((struct headname *)((elm)->field.tqe_prev))->tqh_last)` 即为:
 * `(((struct entryname *)((elm)->field.tqe_prev))->tqe_prev)`. 前第二个元素的 tqe_next. 
 */
#define    TAILQ_PREV(elm, headname, field)                \
    (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
    
#define    TAILQ_FOREACH(var, head, field)                    \
    for ((var) = TAILQ_FIRST((head));                \
        (var);                            \
        (var) = TAILQ_NEXT((var), field))

#define    TAILQ_INIT(head) do {                
    TAILQ_FIRST((head)) = NULL;                    \
    (head)->tqh_last = &TAILQ_FIRST((head));    \  // tqh_last 为 头结点本身的 tqh_first指针的地址
} while (0)

#define    TAILQ_CONCAT(head1, head2, field) do {    \ // 合并两个queue
    if (!TAILQ_EMPTY(head2)) {                    \ // 若q2 不为空
        *(head1)->tqh_last = (head2)->tqh_first;\ // 调整 q1 末尾节点的 tqe_next
        (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;    \ // 调整q2 第一个节点的tqe_prev
        (head1)->tqh_last = (head2)->tqh_last;            \ 
        TAILQ_INIT((head2));                    \ // 重置q2的头结点
    }                                \
} while (0)

#define    TAILQ_INSERT_AFTER(head, listelm, elm, field) do {        \ // 将elm 插到 listelm 后面
    if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ // elm->next=listelm->next
        TAILQ_NEXT((elm), field)->field.tqe_prev =        \ // 若listelm不为队尾, 调整elm->next->pre
            &TAILQ_NEXT((elm), field);                \
    else                                \
        (head)->tqh_last = &TAILQ_NEXT((elm), field);        \ // listelm为队尾, 调整tqh_last
    TAILQ_NEXT((listelm), field) = (elm);                \ // 调整listelm->next
    (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);        \ // 调整elm->pre
} while (0)

#define    TAILQ_INSERT_BEFORE(listelm, elm, field) do {            \
    (elm)->field.tqe_prev = (listelm)->field.tqe_prev;        \
    TAILQ_NEXT((elm), field) = (listelm);                \
    *(listelm)->field.tqe_prev = (elm);    \ // 若listelm为第一个元素, 则tqe_prev为 tqh_first  \
    (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);        \
} while (0)

#define    TAILQ_INSERT_HEAD(head, elm, field) do {            \
    if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)    \
        TAILQ_FIRST((head))->field.tqe_prev =            \
            &TAILQ_NEXT((elm), field);                \
    else                                \
        (head)->tqh_last = &TAILQ_NEXT((elm), field); \ // queue为空的情况
    TAILQ_FIRST((head)) = (elm);                    \
    (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ // 第一个元素的 tqe_prev 指向头结点的tqh_first
} while (0)

#define    TAILQ_INSERT_TAIL(head, elm, field) do {            \
    TAILQ_NEXT((elm), field) = NULL;                \
    (elm)->field.tqe_prev = (head)->tqh_last;    \ // 若queue为空, tqh_last 指向 tqh_first
    *(head)->tqh_last = (elm);                    \
    (head)->tqh_last = &TAILQ_NEXT((elm), field);    \
} while (0)

#define    TAILQ_REMOVE(head, elm, field) do {                \
    if ((TAILQ_NEXT((elm), field)) != NULL)                \ // elm 不为队尾, 调整elm->next->pre
        TAILQ_NEXT((elm), field)->field.tqe_prev =        \
            (elm)->field.tqe_prev;                \
    else                                \
        (head)->tqh_last = (elm)->field.tqe_prev;        \ // elm 为队尾, 调整tqh_last
    *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);    \ // 若 elm为队首, 其tqe_prev为 tqh_first
} while (0)
```

 

posted @ 2016-08-25 09:45  brayden  阅读(736)  评论(0编辑  收藏  举报