📄 mytimerheap.c
字号:
/*
*
*mytimerheap.c 定时堆 lin shao chuan
*
*/
#include "mytimerheap.h"
#include <assert.h>
#include "myutility.h"
#include "myheap.h"
#include "mymutex.h"
#include "mylog.h"
typedef struct __mytimerheap_t_
{
HMYMEMPOOL hm;
HMYHEAP hp;
HMYMUTEX protecter;
}mytimerheap_t;
/*
*
*1表示 data1 > data2
*0表示 !(data1 > data2)
*
*/
static __INLINE__ int timer_heap_compare(const void * data1, const void * data2, const void * context)
{
mytimer_node_t * node1 = (mytimer_node_t *)data1;
mytimer_node_t * node2 = (mytimer_node_t *)data2;
assert(node1 && node2);
//超时时间越近,权值越大
if(node1->abs_expire.tv_sec < node2->abs_expire.tv_sec)
return 1;
else if(node1->abs_expire.tv_sec == node2->abs_expire.tv_sec)
{
if(node1->abs_expire.tv_usec <= node2->abs_expire.tv_usec)
return 1;
else
return -1;
}
else
return -1;
}
static __INLINE__ void mytimerheap_inter_destroy(mytimerheap_t * th)
{
if(NULL == th)
return;
MyMutexLock(th->protecter);
if(th->hp)
MyHeapDestruct(th->hp);
th->hp = NULL;
MyMutexUnLock(th->protecter);
MyMutexDestruct(th->protecter);
th->protecter = NULL;
MyMemPoolFree(th->hm, th);
}
/*
*
* 构造定时堆
*
*/
HMYTIMERHEAP MyTimerHeapConstruct(HMYMEMPOOL hm)
{
mytimerheap_t * th = (mytimerheap_t *)MyMemPoolMalloc(hm, sizeof(*th));
if(NULL == th)
return NULL;
th->hm = hm;
th->hp = MyHeapConstruct(hm, 0, NULL, timer_heap_compare);
th->protecter = MyMutexConstruct(th->hm);
if(NULL == th->hp || NULL == th->protecter)
goto MyTimerHeapConstruct_err_;
return (HMYTIMERHEAP)th;
MyTimerHeapConstruct_err_:
mytimerheap_inter_destroy(th);
return NULL;
}
/*
*
* 析构定时堆
*
*/
void MyTimerHeapDestruct(HMYTIMERHEAP hth)
{
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return;
mytimerheap_inter_destroy(th);
}
/*
*
* 添加定时器
*
*@param
mytimer_node_t * node:定时器节点
*@retval 定时器的id NULL:失败
*
*/
HTIMERID MyTimerHeapAdd(HMYTIMERHEAP hth, mytimer_node_t * node)
{
HTIMERID key = NULL;
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th || NULL == node || NULL == node->timeout_cb)
return NULL;
if(0 != MyMutexLock(th->protecter))
return NULL;
if(NULL == th->hp)
goto MyTimerHeapAdd_end_;
key = (HTIMERID)MyHeapPush(th->hp, node, sizeof(*node));
MyTimerHeapAdd_end_:
MyMutexUnLock(th->protecter);
return key;
}
/*
*
* 删除定时器
*
*/
int MyTimerHeapDel(HMYTIMERHEAP hth, HTIMERID timerid)
{
int ret = 0;
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return -1;
if(0 != MyMutexLock(th->protecter))
return -1;
if(NULL == th->hp)
goto MyTimerHeapDel_end_;
ret = MyHeapDel(th->hp, (HMYHEAP_KEY)timerid);
MyTimerHeapDel_end_:
MyMutexUnLock(th->protecter);
return ret;
}
/*
*
* 重置定时器
*
*@param first_expire:第一次超时(绝对时间) period:定时触发的间隔
*@retval 0:成功 -1:失败
*
*/
HTIMERID MyTimerHeapReset(HMYTIMERHEAP hth, HTIMERID timerid, mytimer_node_t * node)
{
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return NULL;
assert(node && node->timeout_cb);
if(0 != MyMutexLock(th->protecter))
return NULL;
if(NULL == th->hp)
goto MyTimerHeapReset_end_;
timerid = (HTIMERID)MyHeapUpdate(th->hp, (HMYHEAP_KEY)timerid, node, sizeof(*node));
MyTimerHeapReset_end_:
MyMutexUnLock(th->protecter);
return timerid;
}
/*
*
* 获取头节点,即绝对超时最小(最早超时)的键值
*
*/
HTIMERID MyTimeHeapGetEarliestKey(HMYTIMERHEAP hth)
{
HTIMERID timerid = NULL;
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return NULL;
if(0 != MyMutexLock(th->protecter))
return NULL;
if(th->hp)
timerid = (HTIMERID)MyHeapFrontKey(th->hp);
MyMutexUnLock(th->protecter);
return timerid;
}
/*
*
* 获取最小超时(绝对时间)
*
*@retval 0:成功 -1:失败
*
*/
int MyTimerHeapGetEarliestExpire(HMYTIMERHEAP hth, struct timeval * expire)
{
int ret = -1;
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return -1;
assert(expire);
if(0 != MyMutexLock(th->protecter))
return -1;
if(NULL == th->hp)
goto MyTimerHeapGetEarliesExpire_end_;
{
size_t data_size = 0;
mytimer_node_t * n = (mytimer_node_t *)MyHeapFront(th->hp, &data_size);
if(n)
{
assert(sizeof(*n) == data_size);
*expire = n->abs_expire;
ret = 0;
}
else
ret = -1;
}
MyTimerHeapGetEarliesExpire_end_:
MyMutexUnLock(th->protecter);
return ret;
}
/*
*
* 触发所有超时事件
*
*@retval 超时个数
*
*/
unsigned MyTimerHeapRunExpire(HMYTIMERHEAP hth, struct timeval * tv_now)
{
unsigned ret = 0;
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return 0;
assert(tv_now);
if(NULL == th->hp)
goto MyTimerHeapRunExpire_end_;
for(;;)
{
size_t data_size = 0;
unsigned long context_data = 0;
unsigned long timer_user_data = 0;
MY_TIMER_HEAP_TIMEOUT_CB timeout_cb = NULL;
mytimer_node_t n = {0};
mytimer_node_t * n_min = NULL;
if(0 != MyMutexLock(th->protecter))
break;
//依次取出堆中的节点
n_min = (mytimer_node_t *)MyHeapFront(th->hp, &data_size);
//堆中没有节点,结束
if(NULL == n_min)
{
MyMutexUnLock(th->protecter);
break;
}
memcpy(&n, n_min, sizeof(n));
MyMutexUnLock(th->protecter);
assert(sizeof(n) == data_size);
context_data = n.context_data;
timer_user_data = n.timer_user_data;
timeout_cb = n.timeout_cb;
assert(timeout_cb);
//最近的超时未到,说明之后的节点均未超时
if(timeval_smaller(*tv_now, n.abs_expire))
break;
//是否是周期性触发
if(n.period.tv_sec || n.period.tv_usec)
{
HMYHEAP_KEY key = NULL;
//防止已经落后了好几个周期的情况出现 --- 优化此代码,在某些回调函数执行需要很长,而定时间隔又很短的场合,这里要花费大量的时间计算
do
{
timeval_add(n.abs_expire, n.period);
}while(timeval_smaller(n.abs_expire, *tv_now));
if(0 != MyMutexLock(th->protecter))
break;
key = MyHeapFrontKey(th->hp);
MyHeapUpdate(th->hp, key, &n, sizeof(n));
MyMutexUnLock(th->protecter);
}
else
{
if(0 != MyMutexLock(th->protecter))
break;
MyHeapPop(th->hp);
MyMutexUnLock(th->protecter);
}
//呼叫回调函数
timeout_cb(context_data, timer_user_data);
ret ++;
}
MyTimerHeapRunExpire_end_:
return ret;
}
/*
*
* 获取定时器的个数
*
*/
size_t MyTimerHeapGetCount(HMYTIMERHEAP hth)
{
size_t ret = 0;
mytimerheap_t * th = (mytimerheap_t *)hth;
if(NULL == th)
return 0;
if(0 != MyMutexLock(th->protecter))
return 0;
if(th->hp)
ret = MyHeapGetCount(th->hp);
MyMutexUnLock(th->protecter);
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -