pjsip协议栈中定时器的实现详解
2014-04-15 15:38
519 查看
http://blog.csdn.net/sunlion81/article/details/8640795
pjsip协议栈中定时器的实现详解
SIP协议中的用于超市重传或其他用途的定时器(timer)很多,令人头大,很久以前就想到如何实现这些定时器,以前用C coding的时候,就是简单地sleep一下来延时。今天仔细分析了pjsip协议栈中定时器的实现源代码。灰常兴奋地看了...
pjsip也是借鉴别人的实现方法,这在其官网上,作者如是说。
pjsip中管理定时器的数据结构是堆,是采用小顶堆来实现的,该堆为一棵完全二叉树,该完全二叉树采用顺序结构(即是数组)实现。
对于每一个定时器,pjsip中用一个定时器实体结构体来描述,该实体结构体如下:
/**
* This structure represents an entry to the timer.
*/
struct pj_timer_entry
{
/**
* User data to be associated with this entry.
* Applications normally will put the instance of object that
* owns the timer entry in this field.
*/
void *user_data;
/**
* Arbitrary ID assigned by the user/owner of this entry.
* Applications can use this ID to distinguish multiple
* timer entries that share the same callback and user_data.
*/
int id;
/**
* Callback to be called when the timer expires.
*/
pj_timer_heap_callback *cb;
/**
* Internal unique timer ID, which is assigned by the timer heap.
* Application should not touch this ID.
*/
pj_timer_id_t _timer_id;
/**
* The future time when the timer expires, which the value is updated
* by timer heap when the timer is scheduled.
*/
pj_time_val _timer_value;
};
注释已经很清楚了,不细说啦......
另一个很重要的实体结构是延时的时间结构体,其包括时间的s和ms两个域:
/**
* Representation of time value in this library.
* This type can be used to represent either an interval or a specific time
* or date.
*/
typedef struct pj_time_val
{
/** The seconds part of the time. */
long sec;
/** The miliseconds fraction of the time. */
long msec;
} pj_time_val;
上述说了小顶堆,以及定时器实体,还有时间结构,那么究竟怎么实现定时功能呢?
不说大家也猜得到,我们必须提供某种机制来判断定时器是否timeout,怎么判断?pjsip中采用轮询的方式,不断轮询定时器堆(定时器实体构成一个定时器小顶堆)根元素,来判断是否超时的。
首先,pj_timer_heap_create()创建定时器堆;
然后,pj_timer_heap_schedule()来调度定时器,也就是插入到定时器堆中,该函数实现堆的基本操作,一旦一个定时器结构体加入堆,就开始计时,此时,该加入的定时器结构体记录了入堆的当前时刻加上延时时间,也就是将来的定时到的某个时刻;
然后,pj_timer_heap_poll()在某线程或者主线程中不断轮询定时器堆的根元素,并且获取轮询时候的当前时刻,用它来和根元素的超时刻比较,如果根元素的记录时刻小于当前时刻,那么该定时器超时,然后将其从堆中删掉,并调用回调函数,进行超时操作。
上述的定时精度不能说十分准确,单基本够用。
后记:
其实定时器的实现原理很简单,就是创建一种机制来判断当前时刻某定时器是否超时。这个过程是个循环的过程。曾经用c语言采用sleep的方式实现定时,使用函数指针来传回调函数为用户提供API,但是精度远不如上述方式。
pjsip协议栈中定时器的实现详解
SIP协议中的用于超市重传或其他用途的定时器(timer)很多,令人头大,很久以前就想到如何实现这些定时器,以前用C coding的时候,就是简单地sleep一下来延时。今天仔细分析了pjsip协议栈中定时器的实现源代码。灰常兴奋地看了...
pjsip也是借鉴别人的实现方法,这在其官网上,作者如是说。
pjsip中管理定时器的数据结构是堆,是采用小顶堆来实现的,该堆为一棵完全二叉树,该完全二叉树采用顺序结构(即是数组)实现。
对于每一个定时器,pjsip中用一个定时器实体结构体来描述,该实体结构体如下:
/**
* This structure represents an entry to the timer.
*/
struct pj_timer_entry
{
/**
* User data to be associated with this entry.
* Applications normally will put the instance of object that
* owns the timer entry in this field.
*/
void *user_data;
/**
* Arbitrary ID assigned by the user/owner of this entry.
* Applications can use this ID to distinguish multiple
* timer entries that share the same callback and user_data.
*/
int id;
/**
* Callback to be called when the timer expires.
*/
pj_timer_heap_callback *cb;
/**
* Internal unique timer ID, which is assigned by the timer heap.
* Application should not touch this ID.
*/
pj_timer_id_t _timer_id;
/**
* The future time when the timer expires, which the value is updated
* by timer heap when the timer is scheduled.
*/
pj_time_val _timer_value;
};
注释已经很清楚了,不细说啦......
另一个很重要的实体结构是延时的时间结构体,其包括时间的s和ms两个域:
/**
* Representation of time value in this library.
* This type can be used to represent either an interval or a specific time
* or date.
*/
typedef struct pj_time_val
{
/** The seconds part of the time. */
long sec;
/** The miliseconds fraction of the time. */
long msec;
} pj_time_val;
上述说了小顶堆,以及定时器实体,还有时间结构,那么究竟怎么实现定时功能呢?
不说大家也猜得到,我们必须提供某种机制来判断定时器是否timeout,怎么判断?pjsip中采用轮询的方式,不断轮询定时器堆(定时器实体构成一个定时器小顶堆)根元素,来判断是否超时的。
首先,pj_timer_heap_create()创建定时器堆;
然后,pj_timer_heap_schedule()来调度定时器,也就是插入到定时器堆中,该函数实现堆的基本操作,一旦一个定时器结构体加入堆,就开始计时,此时,该加入的定时器结构体记录了入堆的当前时刻加上延时时间,也就是将来的定时到的某个时刻;
然后,pj_timer_heap_poll()在某线程或者主线程中不断轮询定时器堆的根元素,并且获取轮询时候的当前时刻,用它来和根元素的超时刻比较,如果根元素的记录时刻小于当前时刻,那么该定时器超时,然后将其从堆中删掉,并调用回调函数,进行超时操作。
上述的定时精度不能说十分准确,单基本够用。
后记:
其实定时器的实现原理很简单,就是创建一种机制来判断当前时刻某定时器是否超时。这个过程是个循环的过程。曾经用c语言采用sleep的方式实现定时,使用函数指针来传回调函数为用户提供API,但是精度远不如上述方式。
相关文章推荐
- pjsip协议栈中定时器的实现详解
- LwIP协议栈源码详解——TCP/IP协议的实现 TCP定时器
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(九:ARP 表查询)
- Android 定时器实现的几种方式和removeCallbacks失效问题详解
- quartz实现定时功能实例详解(servlet定时器配置方法)
- nginx 定时器实现详解
- 【转】Android 定时器实现的几种方式和removeCallbacks失效问题详解--不错
- 嵌入式协议栈开发问题【软定时器实现】
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(一:前言)
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(三:动态内存管理)
- Spring定时器配置的两种实现方式OpenSymphony Quartz和java Timer详解
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(十:ARP 层流程)
- linux使用select实现精确定时器详解
- linux使用select实现定时器详解
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(六:网络接口结构)
- quartz实现定时功能实例详解(servlet定时器配置方法)
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(二:移植综述)
- linux使用select实现精确定时器详解
- UIScreen详解:定时器,快照,亮度,尺寸等实现方法
- LwIP 协议栈源码详解 ——TCP/IP 协议的实现(七:以太网数据接收)