#include #include #if 0 const int g_time_zone = 8; // 默认东八区 static time_t GetDaySeconds(time_t time, int incdays = 0) { return time_t((time + g_time_zone * 3600)/3600/24 + incdays) * 3600 * 24 - 3600 * g_time_zone; } #endif #define CONFIG_BASE_SMALL 0 #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) #define TVN_SIZE (1 << TVN_BITS) #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) #define INDEX(N) ((base->timer_tick >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK) struct tvec { struct list_head vec[TVN_SIZE]; }; struct tvec_root { struct list_head vec[TVR_SIZE]; }; struct tvec_base { struct timer_list *running_timer; long long timer_tick; list_head free_timer; int free_timer_num; struct tvec_root tv1; struct tvec tv2; struct tvec tv3; struct tvec tv4; struct tvec tv5; }; struct timer_list { struct list_head entry; struct list_head attach_entry; int timer_type; // 0:deadline 1: repeattimer 2:fixedtimer outher:deadline long long expires; int milli_seconds; int fixed_timer_execute_times; struct tvec_base *base; a8::TimerFunc timer_func; a8::TimerAfterFunc timer_after_func; a8::XParams param; }; static void InternalAddTimer(struct tvec_base *base, struct timer_list *timer) { long long expires = timer->expires; long long idx = expires - base->timer_tick; struct list_head *vec; if (idx < 0) { vec = base->tv1.vec + (base->timer_tick & TVR_MASK); }else if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = base->tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { int i = (expires >> TVR_BITS) & TVN_MASK; vec = base->tv2.vec + i; } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; vec = base->tv3.vec + i; } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK; vec = base->tv4.vec + i; } else { int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; vec = base->tv5.vec + i; } list_add_tail(&timer->entry, vec); } static int Cascade(struct tvec_base *base, struct tvec *tv, int index) { /* cascade all the timers from tv up one level */ struct timer_list *timer, *tmp; struct list_head tv_list; // 将tv数组中以index为下标的定时器队列取出,准备搬移 list_replace_init(tv->vec + index, &tv_list); // 根据超时时间,将队列中的定时器重新排队。定时器往上一级时间轮排队的过程就 // 在这里发生。 list_for_each_entry_safe(timer, tmp, &tv_list, entry) { InternalAddTimer(base, timer); } return index; } static inline int DetachTimer(struct timer_list *timer) { if (!list_empty(&timer->entry)) { list_del_init(&timer->entry); } return 1; } static inline void InitTimerList(tvec_base* base, timer_list* timer, int timer_type, int milli_seconds, a8::XParams& param, a8::TimerFunc timer_func, a8::TimerAfterFunc timer_after_func) { INIT_LIST_HEAD(&timer->entry); INIT_LIST_HEAD(&timer->attach_entry); timer->timer_type = timer_type; timer->expires = a8::XGetTickCount() + milli_seconds; timer->milli_seconds = milli_seconds; timer->fixed_timer_execute_times = 0; timer->base = base; timer->timer_func = timer_func; timer->timer_after_func = timer_after_func; timer->param = param; } namespace a8 { void Timer::Init() { base_ = new tvec_base(); base_->running_timer = nullptr; base_->timer_tick = a8::XGetTickCount(); INIT_LIST_HEAD(&base_->free_timer); base_->free_timer_num = 0; for (int j = 0; j < TVN_SIZE; j++) { INIT_LIST_HEAD(base_->tv5.vec + j); INIT_LIST_HEAD(base_->tv4.vec + j); INIT_LIST_HEAD(base_->tv3.vec + j); INIT_LIST_HEAD(base_->tv2.vec + j); } for (int j = 0; j < TVR_SIZE; j++) { INIT_LIST_HEAD(base_->tv1.vec + j); } AddRepeatTimer(1000 * 60 * 5, a8::XParams().SetSender(this), &Timer::GC_TimerFunc); } void Timer::UnInit() { Clear(); delete base_; base_ = nullptr; } void Timer::Update() { #ifdef MONITOR long long start_ns_tick = XGetNanoSeconds(); #endif if (a8::XGetTickCount() >= base_->timer_tick) { UpdateTimer(); } #ifdef MONITOR long long end_ns_tick = XGetNanoSeconds(); if (end_ns_tick - start_ns_tick > g_monitor->timer_max_ns) { g_monitor->timer_max_ns = end_ns_tick - start_ns_tick; } #endif } timer_list* Timer::AddDeadLineTimer(int milli_seconds, a8::XParams param, a8::TimerFunc timer_func, a8::TimerAfterFunc timer_after_func) { timer_list *timer = NewTimerList(); InitTimerList(base_, timer, 0, milli_seconds, param, timer_func, timer_after_func); ModifyTimer(timer, milli_seconds); return timer; } timer_list* Timer::AddDeadLineTimerAndAttach(int milli_seconds, a8::XParams param, a8::TimerFunc timer_func, list_head* attach_list, a8::TimerAfterFunc timer_after_func) { timer_list* timer = AddDeadLineTimer(milli_seconds, param, timer_func, timer_after_func); list_add_tail(&timer->attach_entry, attach_list); return timer; } timer_list* Timer::AddRepeatTimer(int milli_seconds, a8::XParams param, a8::TimerFunc timer_func) { timer_list *timer = NewTimerList(); InitTimerList(base_, timer, 1, milli_seconds, param, timer_func, nullptr); ModifyTimer(timer, milli_seconds); return timer; } timer_list* Timer::AddFixedTimer(int milli_seconds, a8::XParams param, a8::TimerFunc timer_func) { timer_list *timer = NewTimerList(); InitTimerList(base_, timer, 2, milli_seconds, param, timer_func, nullptr); ModifyTimer(timer, milli_seconds); return timer; } void Timer::ModifyTimer(timer_list* timer, int milli_seconds) { DetachTimer(timer); timer->milli_seconds = milli_seconds; if (timer->timer_type == 2) { long long tick = a8::XGetTickCount(); long long today_passed_seconds = time(nullptr) - a8::GetDaySeconds(time(nullptr), 0); timer->expires = (tick - today_passed_seconds * 1000) + milli_seconds; if (timer->fixed_timer_execute_times > 0) { if (timer->expires <= tick) { //已过期 timer->expires += 1000 * 3600 * 24; } } }else { timer->expires = a8::XGetTickCount() + milli_seconds; } InternalAddTimer(base_, timer); } void Timer::DeleteTimer(timer_list* timer) { if (timer->timer_after_func) { timer->timer_after_func(timer->param); } DetachTimer(timer); if (!list_empty(&timer->attach_entry)) { list_del_init(&timer->attach_entry); } AddToFreeList(timer); } timer_list* Timer::GetTimerByAttach(list_head* attach_entry) { if (attach_entry) { timer_list* timer = list_entry(attach_entry, struct timer_list, attach_entry); return timer; } else { return nullptr; } } int Timer::GetIdleableMillSeconds() { #if 0 struct tvec_base *base = base_; #endif int idle_time = 1; for (int lv1_idx = base_->timer_tick & TVR_MASK; lv1_idx < TVR_SIZE; ++lv1_idx) { if (!list_empty(base_->tv1.vec + lv1_idx)) { return idle_time <= 1 ? 1 : idle_time - 1; } ++idle_time; } #if 0 for (int lv2_idx = INDEX(0); lv2_idx < TVN_SIZE; ++lv2_idx) { if (!list_empty(base_->tv2.vec + lv2_idx)) { return idle_time; } idle_time += TVR_SIZE; } #endif return idle_time <= 1 ? 1 : idle_time - 1; } void Timer::UpdateTimer() { struct tvec_base *base = base_; while (a8::XGetTickCount() >= base->timer_tick) { struct list_head work_list; struct list_head *head = &work_list; int index = base->timer_tick & TVR_MASK; if (!index && (!Cascade(base, &base->tv2, INDEX(0))) && (!Cascade(base, &base->tv3, INDEX(1))) && !Cascade(base, &base->tv4, INDEX(2))) { Cascade(base, &base->tv5, INDEX(3)); } ++base->timer_tick; list_replace_init(base->tv1.vec + index, &work_list); while (!list_empty(head)) { struct timer_list *timer; timer = list_first_entry(head, struct timer_list,entry); base->running_timer = timer; if (timer->timer_func) { timer->timer_func(timer->param); } if (timer->timer_after_func) { timer->timer_after_func(timer->param); } switch (timer->timer_type) { case 1: case 2: //循环类定时 fixed timer也是循环定时器 { if (timer->timer_type == 2) { timer->fixed_timer_execute_times++; } ModifyTimer(timer, timer->milli_seconds); } break; default: //deadline timer { DetachTimer(timer); if (!list_empty(&timer->attach_entry)) { list_del_init(&timer->attach_entry); } AddToFreeList(timer); } break; } } } base->running_timer = nullptr; } timer_list* Timer::NewTimerList() { if (!list_empty(&base_->free_timer)) { timer_list* timer = list_first_entry(&base_->free_timer, struct timer_list,entry); list_del_init(&timer->entry); base_->free_timer_num--; return timer; } else { return new timer_list(); } } void Timer::AddToFreeList(timer_list* timer) { list_add_tail(&timer->entry, &base_->free_timer); base_->free_timer_num++; } void Timer::Clear() { auto free_timers = [] (list_head* head) { while (!list_empty(head)) { struct timer_list *timer; timer = list_first_entry(head, struct timer_list,entry); DetachTimer(timer); if (!list_empty(&timer->attach_entry)) { list_del_init(&timer->attach_entry); } delete timer; } }; for (int j = 0; j < TVN_SIZE; j++) { free_timers(base_->tv5.vec + j); free_timers(base_->tv4.vec + j); free_timers(base_->tv3.vec + j); free_timers(base_->tv2.vec + j); } for (int j = 0; j < TVR_SIZE; j++) { free_timers(base_->tv1.vec + j); } free_timers(&base_->free_timer); } void Timer::GC_TimerFunc(const a8::XParams& param) { Timer* timer = (Timer*)param.sender.GetUserData(); int i = 0; while (!list_empty(&timer->base_->free_timer) && timer->base_->free_timer_num > 1000 && i < 1000) { timer_list* timer1 = list_first_entry(&timer->base_->free_timer, struct timer_list, entry); list_del_init(&timer1->entry); delete timer1; timer->base_->free_timer_num--; i++; } } }