[原创]ACE中定时器的实现原理
1.ace中定时器使用方法 例:typedef ACE_Thread_Timer_Queue_Adapter<ACE_Timer_Wheel> ActiveTimer;class CB : public ACE_Event_Handler{public:CB (int id) : id_(id) { }virtual int handle_timeout (const ACE_Time_Value &, const void *arg){ ACE_TRACE (ACE_TEXT ("CB::handle_timeout")); return 0;}private:int id_;};// Listing 2// Listing 3 code/ch20int ACE_TMAIN (int, ACE_TCHAR *[]){ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("the main thread %t has started \n")));ActiveTimer atimer;atimer.activate ();CB cb1 (1);int arg1;const ACE_Time_Value curr_tv = ACE_OS::gettimeofday ();ACE_Time_Value interval1 = ACE_Time_Value (6, 100000);atimer.schedule (&cb1, //event_handler 定时器会在指定时间间隔定时调用它的handle_timeout函数 &arg1, //传入handle_timeout的参数 curr_tv + ACE_Time_Value (3L),//起始时间 interval1); //循环时间间隔ACE_Thread_Manager::instance ()->wait ();// Wait forever.return 0;} 从上面的例子中我们可以清楚地看到定时器掉用的两个关键函数:1.activate() 2.scheduler()。2.ace定时器实现中的相关类 ACE_Task_Base 任务类的基类 ACE_Task 任务类3.ace定时器实现流程 定时器实现的流程 定时器类使用activate启动专用循环线程,随后用户调用定时器类的schedule方法定时器中加入定时单元。 并且ace允许用户向一个定时器中添加多个定时单元,说白了就是允许对同一对象多次调用schedule方法。 1)启动定时器专用线程 在上面的定时器使用方法中可以清楚的看到定时器在使用时首先调用了ACE_Thread_Timer_Queue_Adapter类的activate方法。 我们首先就从该方法入手探其究竟。 在打开ace的相关源代码后我们会看到醒目的一行: return ACE_Task_Base::activate (flags, 1, 0, priority, grp_id, task, 0,stack, stack_size, thread_names); 我们继续跟踪到ACE_Task_Base::activate中还会发现一个重要的函数调用: grp_spawned = this->thr_mgr_->spawn_n (n_threads, &ACE_Task_Base::svc_run, (void *) this, flags, priority, grp_id, task, thread_handles, stack, stack_size); 看到这里,可能有些对ace线程实现机制熟悉的同志已经会心的笑了。对,spawn_n负责启动了定时器循环线程。 不明白也不用急,随后我会将ace线程实现的机制也发布出来供大家讨论。现在大家之需要知道这玩意启动了一个线程就行了。 需要注意spawn_n会启动且只会启动一个线程,引用ace注释的一句话说就是Otherwise, too many weird things can happen。 2)定时器回调函数 当定时器线程被启动后,必然要执行为线程定义的回调函数。ace中提供了ACE_Task_Base::svc_run供定时器线程调用。 而找到相应的源码后,我们会轻易的发现下面两行代码 ACE_Task_Base *t = (ACE_Task_Base *) args; int svc_status = t->svc (); 其实上面代码你可以想象为: int svc_status = this->svc();\\呵呵有人肯定会问为什么要拐这么个湾啊,拜托svc_run为静态函数,而svc不是啊。 由于ACE_Task_Base是一个基类且我们的主角ACE_Thread_Timer_Queue_Adapter正是师承于此,所以我们用膝盖都可以想象 到,ACE_Task_Base::svc方法肯定是什么工作都不会作,呵呵果然。再往下我们的主角就要登场了,ACE_Thread_Timer_Queue_Adapter 中完成了ACE_Task_Base中没有完成的工作,实现了svc()方法.在该方法中会看到一个重要的循环: while (this->active_) { ...省略... this->timer_queue_->expire (); //定时器队列timer_queue中的定时器用于判断是否该自己启动了 } 看到这里又会引入一个ACE_Thread_Timer_Queue_Adapter::timer_queue,这到底是个什么玩艺。看看下面我们也许会受到一些启发 template <class TQ> class ACE_Thread_Timer_Queue_Adapter : public ACE_Task_Base { private: TQ* timer_queue_; } 原来timer_queue_可以有用户在实际运用是选择合适的定时期存储容器(可选容器包括:ACE_Timer_Heap、ACE_Timer_List、ACE_Timer_Wheel等),下面我们以 ACE_Timer_Wheel为例: template <class TYPE, class FUNCTOR, class ACE_LOCK> class ACE_Timer_Wheel_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> { 究根刨底后终于发现原来是 ACE_Event_Handler_Handle_Timeout_Upcall的一个对象。未完待续,欢迎大家和我一起研究。 如果想中途改变interval怎么办呢? 用
ACE_Reactor::Instance()->schedule_timer();
和
->reset_interval();
可以在途中改变interval。但是要在下一次timeout之后才能生效 期待下文ing
页:
[1]