libevent中的基本数据结构
libevent中文件queue.h文件包含5种数据结构:单链表,双向链表,队列,尾队列,环形队列。在处理I/O和signal中的事件时,用的就是尾队列,下面就介绍这几种数据结构
1、单链表
链表头用宏SLIT_HEAD来定义
#define SLIST_HEAD(name, type) \
struct name { \struct type *slh_first; /* first element */ \
}
链表中的元素用宏SLIST_ENTRY定义
#define SLIST_ENTRY(type) \
struct { \struct type *sle_next; /* next element */ \
}
单链表的逻辑结构图表示为
包含的操作有元素后插入,头部插入,头部删除
元素后插入宏定义
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \(elm)->field.sle_next = (slistelm)->field.sle_next; \(slistelm)->field.sle_next = (elm); \
} while (0)
头部插入
#define SLIST_INSERT_HEAD(head, elm, field) do { \(elm)->field.sle_next = (head)->slh_first; \(head)->slh_first = (elm); \
} while (0)
头部删除
#define SLIST_REMOVE_HEAD(head, field) do { \(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
2、双链表
双链表头宏定义为
#define LIST_HEAD(name, type) \
struct name { \struct type *lh_first; /* first element */ \
}
双链表中元素宏定义为
#define LIST_ENTRY(type) \
struct { \struct type *le_next; /* next element */ \struct type **le_prev; /* address of previous next element */ \ //前一个成员le_next的地址
}
逻辑结构图为
元素后插入
#define LIST_INSERT_AFTER(listelm, elm, field) do { \if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \(listelm)->field.le_next->field.le_prev = \&(elm)->field.le_next; \(listelm)->field.le_next = (elm); \(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
逻辑结构图为
元素前插入
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \(elm)->field.le_prev = (listelm)->field.le_prev; \(elm)->field.le_next = (listelm); \*(listelm)->field.le_prev = (elm); \(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
列表头插入
#define LIST_INSERT_HEAD(head, elm, field) do { \if (((elm)->field.le_next = (head)->lh_first) != NULL) \(head)->lh_first->field.le_prev = &(elm)->field.le_next;\(head)->lh_first = (elm); \(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
元素删除
#define LIST_REMOVE(elm, field) do { \if ((elm)->field.le_next != NULL) \(elm)->field.le_next->field.le_prev = \(elm)->field.le_prev; \*(elm)->field.le_prev = (elm)->field.le_next; \
} while (0)
元素替换
#define LIST_REPLACE(elm, elm2, field) do { \if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \(elm2)->field.le_next->field.le_prev = \&(elm2)->field.le_next; \(elm2)->field.le_prev = (elm)->field.le_prev; \*(elm2)->field.le_prev = (elm2); \
} while (0)
3、简单队列
简单队列主要包含头插入,尾插入,元素后插入,头删除操作
/** Simple queue definitions.*///简单队列头定义
#define SIMPLEQ_HEAD(name, type) \
struct name { \struct type *sqh_first; /* first element */ \struct type **sqh_last; /* addr of last next element */ \
}//队列头初始化,sqh_first=NULL, sqh_last=&sql_first
#define SIMPLEQ_HEAD_INITIALIZER(head) \{ NULL, &(head).sqh_first }//简单队列元素定义
#define SIMPLEQ_ENTRY(type) \
struct { \struct type *sqe_next; /* next element */ \
}/** Simple queue access methods.*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first) //队列头
#define SIMPLEQ_END(head) NULL //队列尾
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) //队列空的判断
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) //队列元素的下一个元素//简单队列遍历
#define SIMPLEQ_FOREACH(var, head, field) \for((var) = SIMPLEQ_FIRST(head); \(var) != SIMPLEQ_END(head); \(var) = SIMPLEQ_NEXT(var, field))/** Simple queue functions.*///简单队列初始化
#define SIMPLEQ_INIT(head) do { \(head)->sqh_first = NULL; \(head)->sqh_last = &(head)->sqh_first; \
} while (0)//简单队列头插入元素
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \(head)->sqh_last = &(elm)->field.sqe_next; \(head)->sqh_first = (elm); \
} while (0)//简单队列尾插入元素
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \(elm)->field.sqe_next = NULL; \*(head)->sqh_last = (elm); \(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)//简单队列元素后插入元素
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\(head)->sqh_last = &(elm)->field.sqe_next; \(listelm)->field.sqe_next = (elm); \
} while (0)//队列头部删除元素
#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \(head)->sqh_last = &(head)->sqh_first; \
} while (0)
4、尾队列
尾队列中主要包含队列头插入,尾插入,元素后插入,元素前插入,元素删除,元素替换。libevent中用到的队列其实也是尾队列
/** Tail queue definitions.*///尾队列头定义,其中tqh_last表示最后一个元素的地址
#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)
5、环形队列
操作包含元素前插入, 元素后插入,头插入,尾接入,元素删除,元素替换
/** Circular queue definitions.*///队列头定义
#define CIRCLEQ_HEAD(name, type) \
struct name { \struct type *cqh_first; /* first element */ \struct type *cqh_last; /* last element */ \
}//队列头初始化
#define CIRCLEQ_HEAD_INITIALIZER(head) \{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }//队列元素定义
#define CIRCLEQ_ENTRY(type) \
struct { \struct type *cqe_next; /* next element */ \struct type *cqe_prev; /* previous element */ \
}/** Circular queue access methods*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first) //环形队列中的第一个元素
#define CIRCLEQ_LAST(head) ((head)->cqh_last) //环形队列中的最后一个元素
#define CIRCLEQ_END(head) ((void *)(head))
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) //下一个元素
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) //前一个元素
#define CIRCLEQ_EMPTY(head) \ //环形队列是否为空(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))//环形队列遍历
#define CIRCLEQ_FOREACH(var, head, field) \for((var) = CIRCLEQ_FIRST(head); \(var) != CIRCLEQ_END(head); \(var) = CIRCLEQ_NEXT(var, field))//环形队列反向遍历
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \for((var) = CIRCLEQ_LAST(head); \(var) != CIRCLEQ_END(head); \(var) = CIRCLEQ_PREV(var, field))/** Circular queue functions.*///环形队列初始化
#define CIRCLEQ_INIT(head) do { \(head)->cqh_first = CIRCLEQ_END(head); \(head)->cqh_last = CIRCLEQ_END(head); \
} while (0)//元素后插入
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \(elm)->field.cqe_next = (listelm)->field.cqe_next; \(elm)->field.cqe_prev = (listelm); \if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \(head)->cqh_last = (elm); \else \(listelm)->field.cqe_next->field.cqe_prev = (elm); \(listelm)->field.cqe_next = (elm); \
} while (0)//元素前插入
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \(elm)->field.cqe_next = (listelm); \(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \(head)->cqh_first = (elm); \else \(listelm)->field.cqe_prev->field.cqe_next = (elm); \(listelm)->field.cqe_prev = (elm); \
} while (0)//队列头插入
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \(elm)->field.cqe_next = (head)->cqh_first; \(elm)->field.cqe_prev = CIRCLEQ_END(head); \if ((head)->cqh_last == CIRCLEQ_END(head)) \(head)->cqh_last = (elm); \else \(head)->cqh_first->field.cqe_prev = (elm); \(head)->cqh_first = (elm); \
} while (0)//队列尾插入
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \(elm)->field.cqe_next = CIRCLEQ_END(head); \(elm)->field.cqe_prev = (head)->cqh_last; \if ((head)->cqh_first == CIRCLEQ_END(head)) \(head)->cqh_first = (elm); \else \(head)->cqh_last->field.cqe_next = (elm); \(head)->cqh_last = (elm); \
} while (0)//元素删除
#define CIRCLEQ_REMOVE(head, elm, field) do { \if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \(head)->cqh_last = (elm)->field.cqe_prev; \else \(elm)->field.cqe_next->field.cqe_prev = \(elm)->field.cqe_prev; \if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \(head)->cqh_first = (elm)->field.cqe_next; \else \(elm)->field.cqe_prev->field.cqe_next = \(elm)->field.cqe_next; \
} while (0)//元素替换
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \CIRCLEQ_END(head)) \(head).cqh_last = (elm2); \else \(elm2)->field.cqe_next->field.cqe_prev = (elm2); \if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \CIRCLEQ_END(head)) \(head).cqh_first = (elm2); \else \(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
} while (0)
libevent中的基本数据结构相关推荐
- Java基础-JAVA中常见的数据结构介绍
Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...
- libevent中的bufferevent
bufferevent是libevent中处理网络事件很重要也是比较复杂的一个模块,其中包含一个读事件,一个写事件,两个缓冲区(读和写).读写水位.三个回调(读.写.出错)和函数指针组成的操作集.目前 ...
- libevent中的缓冲区(一)
libevent中的缓冲区定义为evbuffer,主要在文件evbuffer-internal.h文件中,定义如下 struct evbuffer {/** The first chain in ...
- libevent中事件的添加与删除
前面介绍了libevent中的hash表,在添加事件时,具体是如何操作的呢?事件操作主要是在evmap.c文件中,包含了io事件,signal事件的操作.在事件操作时,分两种情况,一种是利用ha ...
- libevent中的信号处理
libevent中将信号集成到event_base_loop事件循环中,通过socketpair转换成I/O事件,本文主要介绍相关的转换. 1.将信号转成I/O 采用socket pair方式,一个s ...
- libevent中的时间及相关的管理
libevent中的时间及相关的管理 在介绍时间之前,先说明几个与时间相关的函数及其用法 1.基础 1.1 clock_gettime(精度比较高,ns级) #include <time.h&g ...
- libevent中的hash表
libevent中的hash表的代码在ht-internal文件中,在添加io事件,signal事件时,底层是在操作 event_io_map和event_signal_map 1. hash的 ...
- Python中的高级数据结构详解
这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...
- Android开发中高效的数据结构用SparseArray代替HashMap
Android开发中高效的数据结构用SparseArray代替HashMap 转载于:https://www.cnblogs.com/zhujiabin/p/5775435.html
最新文章
- SAP MM 移动类型101与103+105组合混用?
- C# Dynamic特性
- 微信红包随机数字_微信红包随机算法转载
- Linux常用50条命令
- 人社部《劳动合同》通用范本模板
- 最新系统分析师考试大纲
- win7计算机资源管理器卡住,win7系统资源管理器出现卡死现象的解决方法
- 北京市参加汽车摇号条件
- 05、Flutter FFI 结构体
- 《WEB开发-阿里云建站》第1章 建站前的准备
- 部分 VIII. A10 Networks
- VBA:MsgBox函数
- 嵌入式培训如何学?什么人适合转行嵌入式开发?
- 转载:Linux下用mutt给QQ邮箱发匿名邮件
- 等额本息与等额本金,从财务管理的角度充分考虑货币时间价值,哪个对于购房人来说更划算?
- Python 无框架实现决策树(DecisionTree)
- 正则表达式大写转小写
- ABAP:增强篇-MIGO过账增强之CHECK方法获取行项目
- c 语言的产生及发展过程,在意识的产生和发展过程中,起决定性作用的是( ) A.人脑B.语言C.物质D.劳动 - 赏学吧...
- s7400plc运行时关闭服务器,S7-400PLC频繁死机