Libevent源码分析-----TAILQ_QUEUE队列

本文深入分析Libevent中的TAILQ_QUEUE队列结构体,解释了队列操作宏函数的工作原理,并通过实例展示了队列的特殊指针操作,包括队尾节点和前一个节点的查找。通过源码解析,揭示了队列内存布局和指针操作的复杂性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        转载请注明出处: http://blog.csdn.net/luotuo44/article/details/38374009



        Libevent源码中有一个queue.h文件,位于compat/sys目录下。该文件里面定义了5个数据结构,其中TAILQ_QUEUE是使得最广泛的。本文就说一下这个数据结构。


队列结构体:

        TAILQ_QUEUE由下面两个结构体一起配合工作。

#define TAILQ_HEAD(name, type)						\
struct name {								\
    struct type *tqh_first;	/* first element */			\
    struct type **tqh_last;	/* addr of last next element */		\
}

//和前面的TAILQ_HEAD不同,这里的结构体并没有name.即没有结构体名。
//所以该结构体只能作为一个匿名结构体。所以,它一般都是另外一个结构体
//或者共用体的成员
#define TAILQ_ENTRY(type)						\
struct {								\
    struct type *tqe_next;	/* next element */			\
    struct type **tqe_prev;	/* address of previous next element */	\
}
        由这两个结构体配合构造出来的队列一般如下图所示:

        

        图中,一级指针指向的是queue_entry_t这个结构体,即存储queue_entry_t这个结构体的地址值。二级指针存储的是一级地址变量的地址值。所以二级指针指向的是图中的一级指针,而非结构体。图中的1,2, 3为队列元素保存的一些值。


队列操作宏函数以及使用例子:

        除了这两个结构体,在queue.h文件中,还为TAILQ_QUEUE定义了一系列的访问和操作函数。很不幸,它们是一些宏定义。这里就简单贴几个函数(准确来说,不是函数)的代码。

#define	TAILQ_FIRST(head)		((head)->tqh_first)

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

#define	TAILQ_INIT(head) do {						\
    (head)->tqh_first = NULL;					\
    (head)->tqh_last = &(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_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)

        这些宏是很难看的,也没必要直接去看这些宏。下面来看一个使用例子。有例子更容易理解。

//队列中的元素结构体。它有一个值,并且有前向指针和后向指针
//通过前后像指针,把队列中的节点(元素)连接起来
struct queue_entry_t
{
    int value;

    //从TAILQ_ENTRY的定义可知,它只能是结构体或者共用体的成员变量
    TAILQ_ENTRY(queue_entry_t)entry;
};

//定义一个结构体,结构体名为queue_head_t,成员变量类型为queue_entry_t
//就像有头节点的链表那样,这个是队列头。它有两个指针,分别指向队列的头和尾
TAILQ_HEAD(queue_head_t, queue_entry_t);

int main(int argc, char **argv)
{
    struct queue_head_t queue_head;
    st
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值