2 定时器
简单的时间轮. 使用时间轮是因为, 定时器数目可能比较大.
要求使用者周期性调用, p_timer_wheel_hb
缺点是, 不精确.
/* Hash table for hold timer list */
static list_header wheel_slot[WHEEL_ELEM];
static unsigned int svd_tick;
static int cur_slot = 0;
#ifndef WIN32
unsigned int GetTickCount()
{
struct timeval current;
unsigned int cur_time;
gettimeofday(¤t, NULL);
cur_time = current.tv_sec*1000 + current.tv_usec/1000;
return cur_time;
}
#endif
unsigned int get_cur_time()
{
return GetTickCount();
}
void p_timer_restart (p_timer_t *new_timer)
{
int target_slot;
list_header *timer_list;
assert(new_timer);
target_slot = (cur_slot + new_timer->period_ms)%WHEEL_ELEM;
new_timer->left_sec = new_timer->period_ms/WHEEL_ELEM;
timer_list = &wheel_slot[target_slot];
list_enqueue_tail(timer_list, &new_timer->list);
}
p_timer_t* p_timer_start (int period_ms,
timer_callback timer_cb,
void *app_context)
{
p_timer_t* new_timer;
int target_slot;
list_header *timer_list;
assert(timer_cb);
assert(period_ms);
new_timer = malloc_obj(sizeof(p_timer_t), TIMER_MEM_OBJ);
assert(new_timer);
new_timer->app_context = app_context;
new_timer->timer_cb = timer_cb;
new_timer->period_ms = period_ms;
new_timer->left_sec = new_timer->period_ms / WHEEL_ELEM;
target_slot = (cur_slot + period_ms)%WHEEL_ELEM;
timer_list = &wheel_slot[target_slot];
list_enqueue_tail(timer_list, &new_timer->list);
return new_timer;
}
BOOL p_timer_running(p_timer_t *timer)
{
if (timer == NULL) {
return FALSE;
}
return (timer->period_ms == 0);
}
BOOL p_timer_stop(p_timer_t *timer)
{
if (timer == NULL) {
return FALSE;
}
timer->period_ms = 0;
return TRUE;
}
void p_timer_wheel_hb()
{
list_header *tmr_list;
list_head *element, *tmp_elem;
p_timer_t *tmr;
unsigned int cur_tick, delta_tick;
cur_tick = GetTickCount();
if (svd_tick == 0) {
svd_tick = cur_tick;
}
delta_tick = cur_tick - svd_tick;
svd_tick = cur_tick;
while (delta_tick--) {
tmr_list = &wheel_slot[cur_slot];
list_for_each_safe(tmr_list, tmp_elem, element) {
tmr = list_entry(element, p_timer_t, list);
if (tmr->left_sec) {
tmr->left_sec--;
continue;
}
list_delink(tmr_list, element);
if (tmr->period_ms == 0) {
free_obj(tmr, TIMER_MEM_OBJ);
} else {
tmr->timer_cb(tmr, tmr->app_context);
p_timer_restart(tmr);
}
}
cur_slot = (cur_slot + 1) % WHEEL_ELEM;
}
return;
}
void timer_proc_exit()
{
int i;
list_head *element, *tmp_elem;
p_timer_t* p_timer;
list_header *tmr_list;
for (i = 0; i < WHEEL_ELEM; i++) {
tmr_list = &wheel_slot[i];
list_for_each_safe(tmr_list, tmp_elem, element) {
p_timer = list_entry(element, p_timer_t, list);
list_delink(tmr_list, element);
free_obj(p_timer, TIMER_MEM_OBJ);
}
}
}
//------------- Internal API --------------------------------------------------
void timer_subsys_init()
{
int i;
svd_tick = 0;
for (i = 0; i< WHEEL_ELEM; i++) {
list_init(&wheel_slot[i]);
}
}
来源:oschina
链接:https://my.oschina.net/u/90010/blog/15336