libevent源码学习(四)定时器Timer
来源:互联网 发布:淘宝好看的跑步鞋店铺 编辑:程序博客网 时间:2024/05/16 07:02
与signal相比,Timer事件的集成会直观和简单很多。
集成到事件主循环
因为系统的I/O机制像select
和epoll_wait
都允许程序制定一个超时时间:
//int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);//int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
即使没有I/O事件的发生,也能保证系统调用在Timeout时间内返回。
那么根据所有timer事件的最小超时时间来设置系统I/O的timeout时间,当系统I/O返回时,再激活所有就绪的Timer事件就可以了。
在event_base_loop
事件循环中,我们很轻易就能找到timeout_next
函数
这个函数根据堆中具有最小超时值的事件和当前时间来计算等待时间
static inttimeout_next(struct event_base *base, struct timeval **tv_p){ /* Caller must hold th_base_lock */ struct timeval now; struct event *ev; struct timeval *tv = *tv_p; int res = 0; //堆的首元素具有最小的超时值 ev = min_heap_top(&base->timeheap); if (ev == NULL) { //没有超时事件,则不进行超时等待,事件循环将一直阻塞直到有IO事件发生 /* if no time-based events are active wait for I/O */ *tv_p = NULL; goto out; } //取得当前时间 if (gettime(base, &now) == -1) { res = -1; goto out; } //如果超时事件<=当前值,不能等待,需要立即返回 //宏真是任性 可以直接用<= 表示小于等于operator if (evutil_timercmp(&ev->ev_timeout, &now, <=)) { evutil_timerclear(tv); goto out; } //计算等待的时间=当前时间-最小超时时间 //这是对timersub的简单封装 evutil_timersub(&ev->ev_timeout, &now, tv); EVUTIL_ASSERT(tv->tv_sec >= 0); EVUTIL_ASSERT(tv->tv_usec >= 0); event_debug(("timeout_next: in %d seconds", (int)tv->tv_sec));out: return (res);}
小根堆
Libevent使用堆来管理Timer事件。向堆中插入、删除元素的时间复杂度都是O(lgN),而获取最小值的时间复杂度是O(1),
堆用数组的形式维护一个完全二叉树,这是堆的基本概念,下面看两个典型实现(伪代码):
heap[size++]=new;child=size;while(child > 0){ parent=(child-1)/2; if(heap[parent].key<heap[child].key) break; swap(parent,child)}
libevent用的办法和stl一样,新元素来时,为新元素预留了一个位置hole,通过比较key和parent,不断的上溯hole,最后确认hole就是新元素应该在的位置时,
才会真正的执行插入操作。
hole=size;while(hole>0){ parent=(hole-1)/2; if(heap[parent].key<new.key) break; heap[hole]=heap[parent]; hole=parent;}heap[hole]=new;size++;
参考
http://blog.csdn.net/zhangxiao93/article/details/72461396
阅读全文
1 0
- libevent源码学习(四)定时器Timer
- Libevent 编程- 定时器事件(timer event)
- libevent timer定时器
- libevent源码学习研究(libevent-0.1)
- Libevent学习-------定时器事件
- Libevent源码分析(四)--- libevent事件机制
- storm定时器timer源码分析-timer.clj
- storm定时器timer源码分析-timer.clj
- FreeRTOS timer定时器源码分析
- Timer定时器实现源码分析
- 定时器-Vision Timer源码分析
- Libevent源码分析-timer和signal处理
- Libevent源码学习(四) 事件内部流程解析下部
- libevent学习四
- libevent 学习笔记 四
- libevent源码深度剖析四
- libevent源码深度剖析四
- libevent源码阅读笔记(四)
- MapReduce 2 的工作机制
- java之非阻塞IO(NIO)
- UVA 11806 Cheerleaders(容斥原理)
- SQL中的case when then else end用法
- Laravel [1045] 解决方法 Access denied for user 'homestead'@'localhost'
- libevent源码学习(四)定时器Timer
- NGINX反向代理服务器
- OpenCV 加载图像的两种接口
- Ubuntu 14.04 LTS嵌入式交叉编译环境arm-linux-gcc搭建过程图解
- 直播系统架构(二)
- __attribute__的妙用整理
- JavaScript的消息机制(转)
- 什么最重要
- 使用Spark MLlib随机森林RandomForest+pipeline进行预测