2 定時器app
簡單的時間輪. 使用時間輪是由於, 定時器數目可能比較大. rest
要求使用者週期性調用, p_timer_wheel_hbelement
缺點是, 不精確.get
/* Hash table for hold timer list */
static list_header wheel_slot[WHEEL_ELEM];
static unsigned int svd_tick;
static int cur_slot = 0;it
#ifndef WIN32
unsigned int GetTickCount()
{
struct timeval current;
unsigned int cur_time;io
gettimeofday(¤t, NULL);
cur_time = current.tv_sec*1000 + current.tv_usec/1000;table
return cur_time;
}
#endif定時器
unsigned int get_cur_time()
{
return GetTickCount();
}queue
void p_timer_restart (p_timer_t *new_timer)
{
int target_slot;
list_header *timer_list;im
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]); } }