libevent数据结构尾队列

来源:互联网 发布:淘宝9.9包邮怎么赚钱 编辑:程序博客网 时间:2024/05/22 06:47

1.概述
最近找来libevent的源码学习了一下,看到用宏实现的数据结构甚是惊讶,把其中尾队列的代码copy出来test了一下.个人感觉用宏实现该队列的思想是C++的模板的思想.我自己实现一个队列的思路肯定是写一个队列 中节点的结构体然后针对该结构体实现队列的基本操作.这样的队列只能使用于写好的节点….而libevent实现的版本是不依赖于实际的节点的.换句话说,我们有两个类,一个student,一个teacher,该队列既可以把student 作为队列连接起来,也可以将teacher连接起来.相当于 TAIQ ,TAIQ. 而且针对同一个结构体(类) 可以实现多个队列,比如说所有学生连接成一个队列,再把其中的男学生连接为一个队列.

2实现

#define TAILQ_HEAD(name, type)                      \struct name {                               \    struct type *tqh_first; /* first element */         \    struct type **tqh_last; /* addr of last next element */     \}#define TAILQ_HEAD_INITIALIZER(head)                    \    { NULL, &(head).tqh_first }#define TAILQ_ENTRY(type)                       \struct {                                \    struct type *tqe_next;  /* next element */          \    struct type **tqe_prev; /* address of previous next element */  \}/* * tail queue access methods */#define TAILQ_FIRST(head)       ((head)->tqh_first)#define TAILQ_END(head)         NULL#define TAILQ_NEXT(elm, field)      ((elm)->field.tqe_next)#define TAILQ_LAST(head, headname)                  \    (*(((struct headname *)((head)->tqh_last))->tqh_last))/* XXX */#define TAILQ_PREV(elm, headname, field)                \    (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))#define TAILQ_EMPTY(head)                       \    (TAILQ_FIRST(head) == TAILQ_END(head))#define TAILQ_FOREACH(var, head, field)                 \    for((var) = TAILQ_FIRST(head);                  \        (var) != TAILQ_END(head);                   \        (var) = TAILQ_NEXT(var, field))#define TAILQ_FOREACH_REVERSE(var, head, headname, field)       \    for((var) = TAILQ_LAST(head, headname);             \        (var) != TAILQ_END(head);                   \        (var) = TAILQ_PREV(var, headname, field))/* * Tail queue functions. */#define TAILQ_INIT(head) do {                       \    (head)->tqh_first = NULL;                   \    (head)->tqh_last = &(head)->tqh_first;              \} while (0)#define TAILQ_INSERT_HEAD(head, elm, field) do {            \    if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)    \        (head)->tqh_first->field.tqe_prev =         \            &(elm)->field.tqe_next;             \    else                                \        (head)->tqh_last = &(elm)->field.tqe_next;      \    (head)->tqh_first = (elm);                  \    (elm)->field.tqe_prev = &(head)->tqh_first;         \} while (0)#define TAILQ_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 (0)#define TAILQ_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 (0)#define TAILQ_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 (0)#define TAILQ_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 (0)#define TAILQ_REPLACE(head, elm, elm2, field) do {          \    if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \        (elm2)->field.tqe_next->field.tqe_prev =        \            &(elm2)->field.tqe_next;                \    else                                \        (head)->tqh_last = &(elm2)->field.tqe_next;     \    (elm2)->field.tqe_prev = (elm)->field.tqe_prev;         \    *(elm2)->field.tqe_prev = (elm2);               \} while (0)

3测试
针对最后一个功能点进行了简单的测试,以加深记忆和理解

#include "queue.h"#include <stdio.h>#include <stdlib.h>#define NQUEUE 5struct event{    TAILQ_ENTRY(event) queue_field;    TAILQ_ENTRY(event)  active_queue_field;    int start;};TAILQ_HEAD(eventqueue,event);TAILQ_HEAD(activequeue,event);struct eventqueue event_queue_head;struct activequeue active_queue_head;void init(){    TAILQ_INIT(&event_queue_head);    TAILQ_INIT(&active_queue_head);}int main(){    init();    int i;    struct  event *e = NULL;    for(i = 0; i < NQUEUE; i++){        e =(struct event*)malloc(sizeof(struct event));        e->start = i;        TAILQ_INSERT_TAIL(&event_queue_head,e,queue_field);        if(i %2 == 0)            TAILQ_INSERT_TAIL(&active_queue_head,e,active_queue_field);    }    struct event* var = NULL;    TAILQ_FOREACH(var,&event_queue_head,queue_field){        printf("the value is %d\n",var->start);    }    printf("\n");    TAILQ_FOREACH(var,&active_queue_head,active_queue_field){        printf("the value is %d\n",var->start);    }    return 0;}

实现了一个结构体 event , 申请了5个event 并把它们连接成两个队列.一个队列中包含了所有的event,一个队列中包含了值为偶数的event.

打印结果:

~/xxxx ᐅ ./a.outthe value is 0the value is 1the value is 2the value is 3the value is 4the value is 0the value is 2the value is 4