6 尽量使用ID取消ACE_Event_Handler定时器
ACE的Reactor 提供了两种方式取消定时器:
virtual int cancel_timer (ACE_Event_Handler *event_handler,
int dont_call_handle_close = 1);
virtual int cancel_timer (long timer_id,
const void **arg = 0,
int dont_call_handle_close = 1);
一种是使用定时器ID取消定时器,这个ID是定时器是的返回值,一种是采用相应的ACE_Event_Handler指针取消定时器。一般情况下使用ACE_Event_Handler的指针取消定时器无疑是最简单的方法,但是这个方法却不是一个高效的实现。所以如果您的程序有大规模的定时器设置取消操作,建议尽量使用ID取消定时器。我们用ACE_Timer_Heap和ACE_Timer_Has两个Timer_Queue剖析一下。
6.1 ACE_Timer_Heap如何根据Event_handler取消
先选择最常用的Time_Queue ACE_Timer_Heap举例,其使用ACE_Event_Handler关闭定时器的代码是:
template <class TYPE, class FUNCTOR, class ACE_LOCK> int
ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type,
int dont_call)
{
// Try to locate the ACE_Timer_Node that matches the timer_id.
//循环比较所有的的ACE_Event_Handler的指针是否相同
for (size_t i = 0; i < this->cur_size_; )
{
if (this->heap_[i]->get_type () == type)
{
………………
}
}
而使用TIMER_ID关闭的代码如下,它是通过数组下标进行的定位操作。
template <class TYPE, class FUNCTOR, class ACE_LOCK> int
ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
const void **act,
int dont_call)
{
//通过数组下标操作,速度当然奇快无比。
ssize_t timer_node_slot = this->timer_ids_[timer_id];
……
//跟进数组ID进行操作
else
{
ACE_Timer_Node_T<TYPE> *temp =
this->remove (timer_node_slot);
}
}
对于ACE_Timer_Heap,采用ACE_Event_Handler指针取消定时器的方式的平均时间复杂度应该就是O(N)。由于ACE的的一个Event_handler可能对应多个定时器,所以必须检查所有的才能确保取消所有的相关定时器。
6.2 ACE_Timer_Hash如何根据Event_handler取消
对于Timer_Hash,其通过ACE_Event_Handler关闭定时器的代码是:
template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type,
int dont_call)
{
Hash_Token<TYPE> **timer_ids = 0;
//根据Event Handler有一个定时器new一个数组出来
ACE_NEW_RETURN (timer_ids,
Hash_Token<TYPE> *[this->size_],
-1);
size_t pos = 0;
//根据定时器的个数再进行取消
for (i = 0;
i < this->table_size_;
++i)
{
ACE_Timer_Queue_Iterator_T<TYPE,
ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>,
ACE_Null_Mutex> &iter =
this->table_[i]->iter ();
可以看到Timer_Hash的cancel比ACE_Timer_Heap的cancel(Event_Handler)要好一点点。但是其中也有new和delete操作,这些操作也不是高效操作。
所以说在大规模的定时器使用中,推荐你还是使用定时器的ID取消定时器更加高效的多。