1) ACE_Thread_Timer_Queue_Adapter类的几个关键方法
调度定时器方法
- /// Schedule the timer according to the semantics of the <TQ>; wakes
- /// up the dispatching thread.
- long schedule (ACE_Event_Handler *handler,
- const void *act,
- const ACE_Time_Value &future_time,
- const ACE_Time_Value &interval = ACE_Time_Value::zero);
- /// Cancel the @a timer_id and return the @a act parameter if an
- /// address is passed in. Also wakes up the dispatching thread.
- int cancel (long timer_id, const void **act = 0);
- /// Runs the dispatching thread.
- virtual int svc (void);
- /// Inform the dispatching thread that it should terminate.
- virtual void deactivate (void);
- /**
- * Block until there are no more threads running in this task.
- * This method will not wait for either detached or daemon threads;
- * the threads must have been spawned with the @c THR_JOINABLE flag.
- * Upon successful completion, the threads have been joined, so further
- * attempts to join with any of the waited-for threads will fail.
- *
- * @retval 0 Success.
- * @retval -1 Failure (consult errno for further information).
- */
- virtual int wait (void);
- /**
- * We override the default activate() method so that we can ensure
- * that only a single thread is ever spawned. Otherwise, too many
- * weird things can happen...
- */
- virtual int activate (long flags = THR_NEW_LWP | THR_JOINABLE,
- int n_threads = 1,
- int force_active = 0,
- long priority = ACE_DEFAULT_THREAD_PRIORITY,
- int grp_id = -1,
- ACE_Task_Base *task = 0,
- ACE_hthread_t thread_handles[] = 0,
- void *stack[] = 0,
- size_t stack_size[] = 0,
- ACE_thread_t thread_names[] = 0);
- /// 结束定时器时候需要依次调用
- m_activeTimer.deactivate();
- m_activeTimer.wait();
- m_activeTimer.close();
2)ace定时器在结束的时候需要wait等待,从这点上看ace定时器用线程实现的。在window下每增加一定时器,就会多一个线程(cancel并不能减少线程,只是让定时器也不工作了,不会在定时回调,但是从资源管理器的线程的数目来看,线程没有结束。)
3)ace默认的是THR_JOINABLE有效,也就是说需要等待,cancel后线程迟迟不结束,因为ace中是定时器队列为空的时候并没有把分发线程结束掉,需要手动结束掉,因为即使定时器队列为空,可能在定时器队列中在加入一个新的定时器。
4)如果一个进程或者线程中只有一个定时器,那么可以不需要定时器队列来管理,只在进行中增加一个定时器,从任务管理器上看会增加一个线程,这个线程可以理解为对定时器队列进行操作的线程,一个进程中增加两个定时器到一个定时器队列中,这个时候共用一个线程。
5)“如果一个定时器处理长时间的任务,那么下一个定时器要等上一个处理完后才开始计时”,这个结论是错误的,至少ace的定时器不是这样的,定时器底层实现应该是个消息机制,当定时器时间到的时候就会发送一个消息通知,然后回调定时接口,如果这个时候回调处理时间长也不会影响定时器消息触发。在ace的定时器中如果回调处理的时间超过定时器定时回调的时间,那么当回调接口处理完后会立刻在回调一次。所以用线程简单的sleep下然后调用下回调方法是不对的,到可以用连个线程模拟,一个产生定时器触发消息,定时的(可以用sleep)向消息队列发送触发消息。一个线程监视消息队列,当有触发消息时候就调用回调接口。
6)调用消息队列的schedule实质上是增加了一个定时器,返回增加的定时器的id,并没有启动定时器线程,当调用active的时候才启动了分发线程。调用deactivate的目的是Inform the dispatching thread that it should terminate,也就是结束在定时器队列上操作的分发线程,wait与close是ACE_Task_Base中的方法,一般不会调用close方法,但是这里没有使用主动对象,手动调用close方法(ace 注释是这么说的)。
7)等待定时器与用户定时器:window下的两个定时器,等待定时器是一个内核对象,精度较高,多线程共享,安全,可以触发多个操作。而用户定时器从名字上看就是在用户空间实现的,精度不是很高,用户定时器能够生成WM_TIMER消息,这些消息将返回给调用SetTimer(用于回调定时器)的线程和创建窗口(用于基于窗口的定时器)的线程。因此,当用户定时器报时的时候,只有一个线程得到通知。
8)tcp协议栈使用的是什么定时器?可能也是操作系统提供的定时器,要知道需要看下tcp/ip详解的卷二了。