本文主要研究libevent中用来存储事件的两个结构体。

尾队列

具体定义位于queue.h中。

#define    TAILQ_HEAD(name, type)                        \
struct name {                                \struct type *tqh_first;    /* first element */            \struct type **tqh_last;    /* addr of last next element */        \
}#define    TAILQ_ENTRY(type)                        \
struct {                                \struct type *tqe_next;    /* next element */            \struct type **tqe_prev;    /* address of previous next element */    \
}                                    #define    TAILQ_EMPTY(head)    ((head)->tqh_first == NULL)
#define    TAILQ_FIRST(head)    ((head)->tqh_first)
#define    TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)#define    TAILQ_INIT(head) do {                        \TAILQ_FIRST((head)) = NULL;                    \(head)->tqh_last = &TAILQ_FIRST((head));            \
} while (0)#define    TAILQ_INSERT_TAIL(head, elm, field) do {            \TAILQ_NEXT((elm), field) = NULL;                \(elm)->field.tqe_prev = (head)->tqh_last;            \*(head)->tqh_last = (elm);                    \(head)->tqh_last = &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);        \TAILQ_FIRST((head)) = (elm);                    \(elm)->field.tqe_prev = &TAILQ_FIRST((head));            \
} while (0)#define    TAILQ_INSERT_AFTER(head, listelm, elm, field) do {        \if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\TAILQ_NEXT((elm), field)->field.tqe_prev =         \&TAILQ_NEXT((elm), field);                \else {                                \(head)->tqh_last = &TAILQ_NEXT((elm), field);        \}                                \TAILQ_NEXT((listelm), field) = (elm);                \(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);        \
} 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)->field.tqe_prev = &TAILQ_NEXT((elm), field);        \
} while (0)#define    TAILQ_REMOVE(head, elm, field) do {                \if ((TAILQ_NEXT((elm), field)) != NULL)                \TAILQ_NEXT((elm), field)->field.tqe_prev =         \(elm)->field.tqe_prev;                \else {                                \(head)->tqh_last = (elm)->field.tqe_prev;        \}                                \*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);        \
} while (0)

从定义可以看出,尾队列是一个双向链表,具体表现为:

一个小DEMO:

#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>#define LIST_SIZE 5// 声明头结点
TAILQ_HEAD(event_list, event);
// 声明元素结点
struct event {int value;TAILQ_ENTRY(event) field;
};int main(int argc, char **argv) {event_list *list = (event_list*)malloc(sizeof(event_list));TAILQ_INIT(list);event *item;for (int i = 0; i < LIST_SIZE; i++) {item = (event*)malloc(sizeof(event));item->value = i;item->field.tqe_next = NULL;item->field.tqe_prev = NULL;TAILQ_INSERT_TAIL(list, item, field);}printf("当前list: ");for (item = list->tqh_first; item; item = item->field.tqe_next) {printf("%d ", item->value);}printf("\n");event **test = list->tqh_first->field.tqe_prev;if (test == &list->tqh_first) {printf("guess right\n");}printf("尾部插入结点: 10\n");item = (event*)malloc(sizeof(event));item->value = 10;item->field.tqe_next = NULL;item->field.tqe_prev = NULL;TAILQ_INSERT_TAIL(list, item, field);printf("当前list: ");for (item = list->tqh_first; item; item = item->field.tqe_next) {printf("%d ", item->value);}printf("\n");printf("头部插入结点: 20\n");item = (event*)malloc(sizeof(event));item->value = 20;item->field.tqe_next = NULL;item->field.tqe_prev = NULL;TAILQ_INSERT_HEAD(list, item, field);printf("当前list: ");for (item = list->tqh_first; item; item = item->field.tqe_next) {printf("%d ", item->value);}printf("\n");printf("在值为3的结点之后插入结点: 30\n");for (item = list->tqh_first; item; item = item->field.tqe_next) {if (item->value == 3) {event *new_item = (event*)malloc(sizeof(event));new_item->value = 30;new_item->field.tqe_next = NULL;new_item->field.tqe_prev = NULL;TAILQ_INSERT_AFTER(list, item, new_item, field);}}printf("当前list: ");for (item = list->tqh_first; item; item = item->field.tqe_next) {printf("%d ", item->value);}printf("\n");printf("在值为1的结点之前插入结点: 40\n");for (item = list->tqh_first; item; item = item->field.tqe_next) {if (item->value == 1) {event *new_item = (event*)malloc(sizeof(event));new_item->value = 40;new_item->field.tqe_next = NULL;new_item->field.tqe_prev = NULL;TAILQ_INSERT_BEFORE(item, new_item, field);}}printf("当前list: ");for (item = list->tqh_first; item; item = item->field.tqe_next) {printf("%d ", item->value);}printf("\n");printf("删除值为3的结点\n");for (item = list->tqh_first; item; item = item->field.tqe_next) {if (item->value == 3) {TAILQ_REMOVE(list, item, field);}}printf("当前list: ");for (item = list->tqh_first; item; item = item->field.tqe_next) {printf("%d ", item->value);}printf("\n");printf("Done\n");
}

View Code

最小堆

typedef struct min_heap
{struct event** p; // 指向event*指针数组unsigned n, a;   // a表示堆的大小,n表示堆中元素个数
} min_heap_t;

void min_heap_ctor(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; }
void min_heap_elem_init(struct event* e) { e->ev_timeout_pos.min_heap_idx = -1; }
unsigned min_heap_size(min_heap_t* s) { return s->n; }

参考资料:

do {...} while (0) 的用途汇总(欢迎补充)

转载于:https://www.cnblogs.com/gattaca/p/7680085.html

libevent(二)尾队列 最小堆相关推荐

  1. libevent数据结构尾队列

    1.概述 最近找来libevent的源码学习了一下,看到用宏实现的数据结构甚是惊讶,把其中尾队列的代码copy出来test了一下.个人感觉用宏实现该队列的思想是C++的模板的思想.我自己实现一个队列的 ...

  2. WebServer代码解读(3)【最小堆定时器与队列】

    文章目录 1 - 处理事件 1-1 接收新连接 1-2 最小堆定时器 1-4 将request加入线程池 1-5 处理request 1 - 处理事件 因为epoll_wait函数已经返回了需要处理的 ...

  3. 优先级队列(最大、最小堆)总结

    优先级队列 前言 一.优先级队列 二.与普通队列的对比 三.优先级队列的实现(最大堆) 1.最大堆的实现 2.优先级队列的实现 四.优先级队列的应用 1.创建优先级队列 2.使用优先级队列 五.使用优 ...

  4. 使用最小堆使用优先级队列(c语言版本)

    下面的例子来自Weiss的<数据结构与算法分析:c语言描述>,自己亲自敲了一遍,跑了个demo,并将结果记录下来. binheap.h的头文件声明 //description: 使最小堆实 ...

  5. 优先级队列 c语言,使用最小堆使用优先级队列(c语言版本)

    下面的例子来自Weiss的<数据结构与算法分析:c语言描述>,自己亲自敲了一遍,跑了个demo,并将结果记录下来. binheap.h的头文件声明 //description: 使最小堆实 ...

  6. java队列优先级_优先级队列-Java的PriorityQueue与最小堆有何不同?

    来自Java文档 表示为平衡二进制堆的优先级队列:queue [n]的两个子级是queue [2 * n + 1]和queue [2 *(n + 1)]. 优先级队列由比较器或元素的自然顺序进行排序. ...

  7. 【数据结构与算法】二项队列与二叉堆的比较

    导语 二叉堆确实是入门级的重要数据结构了,而二项队列也是慢慢要去掌握的一种支持高效合并的优先队列实现.本文稍作比较,望抛砖引玉. 列个表格比较基本操作性能 基本操作 insert(平均) delete ...

  8. 《恋上数据结构第1季》二叉堆原理及实现、最小堆解决 TOP K 问题

    二叉堆 BinaryHeap 堆(Heap) 堆的出现 堆简介 二叉堆(Binary Heap) 获取最大值 最大堆 - 添加 最大堆 - 添加优化 最大堆 - 删除 replace 最大堆 - 批量 ...

  9. 数据结构与算法--二叉堆(最大堆,最小堆)实现及原理

    二叉堆(最大堆,最小堆)实现及原理 二叉堆与二叉查找树一样,堆也有两个性质,即结构性质和堆性质.和AVL树一样,对堆的一次操作必须到堆的所有性质都被满足才能终止,也就是我们每次对堆的操作都必须对堆中的 ...

最新文章

  1. 原码、反码、补码解析,保证一次搞懂
  2. 分享HTML5 canvas 的总结
  3. TabHost与RadioGroup结合完成的菜单【带效果图】5个Activity
  4. 【直播回放】2小时全面剖析图像分类任务,学习CV必知
  5. Mongodb数据库(1.mongodb的介绍(非关系型数据库)下载与安装(Windows10))
  6. MongoDB解决“Error parsing YAML config file: yaml-cpp: error at line 2, column value(安装服务)
  7. java 反射 镜子,java反射机制 - 巍巍的个人页面 - OSCHINA - 中文开源技术交流社区...
  8. linux(Ubuntu)常用命令整理 -- 基础篇 -- 持续更新
  9. 艾伟_转载:.NET Discovery 系列之二--string从入门到精通(勘误版下)
  10. linux 常识笔记 20160621
  11. 开源,不是一种道德绑架
  12. pcie routing
  13. Batch Normalization 算法解析
  14. VMware Workstation 12激活码
  15. win7 美化Linux,让XP的主题背景拥有Win7一样的华丽 让Linux系统和Win8一模一样!超华丽Linux仿Win...
  16. ctfshow-菜狗杯-web(一)
  17. 成考本科计算机找工作有用吗,成人本科学历找工作有用吗 就业困难吗
  18. 使用rpc(thrift或protobuf)进行前后端交互的若干种方式
  19. 面试再问ThreadLocal,别说你不会!
  20. STA分析(六) cross talk and noise

热门文章

  1. Linux命令·ln
  2. WPARAM与LPARAM 之区别
  3. 虚函数、虚指针和虚表
  4. 如何利用本地硬盘装系统?教你快速装系统
  5. SQL日期、转换、通用函数
  6. srm555 div2
  7. AJ-Report小白配置大屏手册
  8. 安卓屏幕朗读app_平南小学英语app安卓下载-平南小学英语2020手机版
  9. oracle times ten 学习笔记
  10. cadence SPB17.4 - allegro - 手工放置过孔