ACE_Select_Reactor_T 介绍 (2)
本章目录
- ACE_Select_Reactor_T 介绍
- 类继承图
- 类协作图
- 类主要成员变量
- 事件处理函数调用图
- 事件处理主流程
- handle_events 函数流程
- handle_events_i 函数流程
2. ACE_Select_Reactor_T 介绍
该类继承自类ACE_Select_Reactor_Impl,实现了对IO时间、信号量、定时器的分发处理,公共的函数需要ACE_Reactor_Token进行锁定。typedef ACE_Select_Reactor_T
2.1. 类继承图

2.2. 类协作图

ACE_Select_Reactor 核心交互图,表明了 ACE_Select_Reactor 针对 Socket/IO, 定时器,通知和信号量的整体数据结构。

2.3. 类主要成员变量
ACE_Select_Reactor_Impl继承自 ACE_Reactor_Impl,在类ACE_Select_Reactor_Impl中定义了常用的成员变量:
ace/Select_Reactor_Base.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
/// 提供 |
注解
其中ACE_Select_Reactor_Handler_Repository handler_rep_的数据结构定义,可参见 bind 函数 。
2.4. 事件处理函数调用图

注解
calculate_timeout 函数的调用为类实现中 timer_queue_ 时间队列中最早到期时间,以便设置后续 select 调用函数的超时时间,从而实现了时间队列与IO句柄触发的整合。
2.5. 事件处理主流程
ace/Reactor.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
int ACE_Reactor::run_reactor_event_loop (ACE_Time_Value &tv, REACTOR_EVENT_HOOK eh) { ACE_TRACE ("ACE_Reactor::run_reactor_event_loop"); if (this->reactor_event_loop_done ()) return 0; while (1) { int result = this->implementation_->handle_events (tv); if (eh != 0 && (*eh) (this)) continue; else if (result == -1) { if (this->implementation_->deactivated ()) result = 0; return result; } else if (result == 0) { // The |
行12行,Reactor调用了其实现者的 handle_events(ACE_Time_Value *max_wait_time) 函数,实现类的handle_event函数承担了主要工作的分发和处理。
2.5.1. handle_events 函数流程
ace/Select_Reactor_T.cpp handle_events 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
template <class ACE_SELECT_REACTOR_TOKEN> int ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events (ACE_Time_Value *max_wait_time) { ACE_TRACE ("ACE_Select_Reactor_T::handle_events"); // Stash the current time -- the destructor of this object will // automatically compute how much time elapsed since this method was // called. ACE_Countdown_Time countdown (max_wait_time); #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1); if (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_) == 0) { errno = EACCES; return -1; } if (this->deactivated_) { errno = ESHUTDOWN; return -1; } // Update the countdown to reflect time waiting for the mutex. countdown.update (); #else if (this->deactivated_) { errno = ESHUTDOWN; return -1; } #endif /* ACE_MT_SAFE */ return this->handle_events_i (max_wait_time); } |
2.5.2. handle_events_i 函数流程
ace/Select_Reactor_T.cpp handle_events_i 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
template <class ACE_SELECT_REACTOR_TOKEN> int ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events_i (ACE_Time_Value *max_wait_time) { int result = -1; ACE_SEH_TRY { // We use the data member dispatch_set_ as the current dispatch // set. // We need to start from a clean dispatch_set this->dispatch_set_.rd_mask_.reset (); this->dispatch_set_.wr_mask_.reset (); this->dispatch_set_.ex_mask_.reset (); int number_of_active_handles = this->wait_for_multiple_events (this->dispatch_set_, max_wait_time); result = this->dispatch (number_of_active_handles, this->dispatch_set_); } ACE_SEH_EXCEPT (this->release_token ()) { // As it stands now, we catch and then rethrow all Win32 // structured exceptions so that we can make sure to release the // |
行18, this->wait_for_multiple_events (this->dispatch_set_,max_wait_time) 实现了对于可分发句柄集的获取。
行21,this->dispatch (number_of_active_handles,this->dispatch_set_) 实现了对于分发句柄集的处理。
2.5.2.1. wait_for_multiple_events 函数
ace/Select_Reactor_T.cpp wait_for_multiple_events 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
// Must be called with lock held. template <class ACE_SELECT_REACTOR_TOKEN> int ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &dispatch_set, ACE_Time_Value *max_wait_time) { ACE_TRACE ("ACE_Select_Reactor_T::wait_for_multiple_events"); ACE_Time_Value timer_buf (0); ACE_Time_Value *this_timeout = 0; int number_of_active_handles = this->any_ready (dispatch_set); // If there are any bits enabled in the |
行12,,this->any_ready(dispatch_set) 实现了获取不需要select函数触发的其他类型满足触发条件的句柄
行25-26,this->timer_queue_->calculate_timeout(max_wait_time,&timer_buf) 实现了对定时器队列的超时的计算
行38-42,ACE_OS::select(width,dispatch_set.rd_mask_,dispatch_set.wr_mask_,dispatch_set.ex_mask_,this_timeout) 实现了对使用select函数返回的已触发的handle的跟踪
2.5.2.2. dispatch 函数
ace/Select_Reactor_T.cpp dispatch 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
template <class ACE_SELECT_REACTOR_TOKEN> int ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch (int active_handle_count, ACE_Select_Reactor_Handle_Set &dispatch_set) { ACE_TRACE ("ACE_Select_Reactor_T::dispatch"); int io_handlers_dispatched = 0; int other_handlers_dispatched = 0; int signal_occurred = 0; // The following do/while loop keeps dispatching as long as there // are still active handles. Note that the only way we should ever // iterate more than once through this loop is if signals occur // while we're dispatching other handlers. do { // We expect that the loop will decrease the number of active // handles in each iteration. If it does not, then something is // inconsistent in the state of the Reactor and we should avoid // the loop. Please read the comments on bug 2540 for more // details. int initial_handle_count = active_handle_count; // Note that we keep track of changes to our state. If any of // the dispatch_*() methods below return -1 it means that the // |
处理顺序:
- dispatch_timer_handlers 处理分发定时器,定时器的处理优于Socket/IO的处理。 展开流程见: 定时器与Select_Reactor的分发集成。
- dispatch_notification_handlers 处理分发通知类消息。展开流程见: 通知与Select_Reactor 的分发集成。
- dispatch_io_handlers 处理分发 io handlers。展开流程见: IO句柄与Select_Reactor的分发集成。