ACE_Reactor是如何做到事件分发的

1. ACE_Reactor的创建
ctor: ACE_Reactor (ACE_Reactor_Impl *implementation = 0, int delete_implementation = 0);
你可以自己创建一个ACE_Reactor
但是大多数时候,我们都是通过调用ACE_Reactor::instance()这个静态方法来返回唯一的实例。

ACE_Reactor  *
ACE_Reactor::instance (
void )
{
  ACE_TRACE (
" ACE_Reactor::instance " );

  
if  (ACE_Reactor::reactor_  ==   0 )  //1
    {
      
//  Perform Double-Checked Locking Optimization.
      ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
                                
* ACE_Static_Object_Lock::instance (),  0 ));

      
if  (ACE_Reactor::reactor_  ==   0 ) //2
        {
          ACE_NEW_RETURN (ACE_Reactor::reactor_,
                          ACE_Reactor,
                          
0 );
          ACE_Reactor::delete_reactor_ 
=   1 ;
          ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Reactor, ACE_Reactor::reactor_)
        }
    }
  
return  ACE_Reactor::reactor_;
}
注意这点使用了双检测的机制(代码1和2),为了提高效率,不用每次都加锁。

2. Impl手法的运用
ACE_Reactor有个成员变量 ACE_Reactor_Impl *implementation_;
这个implementation_才是真正做事情的东西,典型的Impl手法。
为什么要多一个这个间隔层呢,主要是为了实现跨平台。
因为不同的平台的Reactor差异很大。
在Windows平台,实现这个是ACE_WFMO_Reactor
class  ACE_Export ACE_WFMO_Reactor :  public  ACE_Reactor_Impl

3. Event_Handle的管理
ACE_WFMO_Reactor把要管理的Handle都放在 ACE_WFMO_Reactor_Handler_Repository handler_rep_;
这里要注意的是io_handle和event_handle的区别
io_handle是真正的handle,比如socket_handle, thread_handle
而event_handle是绑定在io_handle上面的事件handle

有代码为证:
 1  int
 2  ACE_WFMO_Reactor::register_handler_i (ACE_HANDLE event_handle,
 3                                        ACE_HANDLE io_handle,
 4                                        ACE_Event_Handler  * event_handler,
 5                                        ACE_Reactor_Mask new_masks)
 6  {
 7     //  If this is a Winsock 1 system, the underlying event assignment will
 8     //  not work, so don't try. Winsock 1 must use ACE_Select_Reactor for
 9     //  reacting to socket activity.
10 
11     //  Make sure that the <handle> is valid
12     if  (io_handle  ==  ACE_INVALID_HANDLE)
13      io_handle  =  event_handler -> get_handle ();
14 
15     if  ( this -> handler_rep_.invalid_handle (io_handle))
16      {
17        errno  =  ERROR_INVALID_HANDLE;
18         return   - 1 ;
19      }
20 
21     long  new_network_events  =   0 ;
22     int  delete_event  =   0 ;
23    auto_ptr  < ACE_Auto_Event >   event ;
24 
25     //  Look up the repository to see if the <event_handler> is already
26     //  there.
27    ACE_Reactor_Mask old_masks;
28     int  found  =   this -> handler_rep_.modify_network_events_i (io_handle,
29                                                            new_masks,
30                                                            old_masks,
31                                                            new_network_events,
32                                                            event_handle,
33                                                            delete_event,
34                                                            ACE_Reactor::ADD_MASK);
35 
36     //  Check to see if the user passed us a valid event; If not then we
37     //  need to create one
38     if  (event_handle  ==  ACE_INVALID_HANDLE)
39      {
40         //  Note: don't change this since some C++ compilers have
41         //  <auto_ptr>s that don't work properly
42        auto_ptr < ACE_Auto_Event >  tmp ( new  ACE_Auto_Event);
43         event   =  tmp;
44        event_handle  =   event -> handle ();
45        delete_event  =   1 ;
46      }
47 
48     int  result  =  ::WSAEventSelect ((SOCKET) io_handle,
49                                   event_handle,
50                                   new_network_events);

可以看到在42行create event,在44复制到event_handle,最后通过 WSAEventSelect将这个io_handle和event_handle绑定在一起了

这个register_handle调用一般都在Event_Handler的open函数中,实现了注册到Reactor中去。

4. 等待事件
如何检测到要发生的socket的事件呢?比如有新的client连接,收发。ACE并不直接调用select函数来取得。
ACE调用 WaitForMultipleObjectsEx来等待事件的发生。ACE这样做的好处是不但可以捕捉socket事件,也可以捕捉到其他事件。前面说过了每一个对应的socket都有一个event_handle与之对应。 WaitForMultipleObjectsEx会将发生事件的socket handle的index返回。这样ACE_Reactor就可以利用这个slot来查到io_handle和event_handler( 注意:event_handle和event_handler是不同的)

 1  DWORD
 2  ACE_WFMO_Reactor::wait_for_multiple_events ( int  timeout,
 3                                               int  alertable)
 4  {
 5     //  Wait for any of handles_ to be active, or until timeout expires.
 6     //  If <alertable> is enabled allow asynchronous completion of
 7     //  ReadFile and WriteFile operations.
 8 
 9     return  ::WaitForMultipleObjectsEx ( this -> handler_rep_.max_handlep1 (),
10                                        this -> handler_rep_.handles (),
11                                       FALSE,
12                                       timeout,
13                                       alertable);
14  }

5.分发事件
根据WaitForMultiObjectEx返回的slot就可以查询到event_handler来调用用户的处理函数了

 1  int
 2  ACE_WFMO_Reactor::complex_dispatch_handler (DWORD slot,
 3                                              ACE_HANDLE event_handle)
 4  {
 5     //  This dispatch is used for I/O entires.
 6 
 7    ACE_WFMO_Reactor_Handler_Repository::Current_Info  & current_info  =
 8       this -> handler_rep_.current_info ()[slot];
 9 
10    WSANETWORKEVENTS events;
11    ACE_Reactor_Mask problems  =  ACE_Event_Handler::NULL_MASK;
12     if  (::WSAEnumNetworkEvents ((SOCKET) current_info.io_handle_,
13                                event_handle,
14                                 & events)  ==  SOCKET_ERROR)
15      problems  =  ACE_Event_Handler::ALL_EVENTS_MASK;
16     else
17      {
18         //  Prepare for upcalls. Clear the bits from <events> representing
19         //  events the handler is not interested in. If there are any left,
20         //  do the upcall(s). upcall will replace events.lNetworkEvents
21         //  with bits representing any functions that requested a repeat
22         //  callback before checking handles again. In this case, continue
23         //  to call back unless the handler is unregistered as a result of
24         //  one of the upcalls. The way this is written, the upcalls will
25         //  keep being done even if one or more upcalls reported problems.
26         //  In practice this may turn out not so good, but let's see. If any
27         //  problems, please notify Steve Huston <[email protected]>
28         //  before or after you change this code.
29        events.lNetworkEvents  &=  current_info.network_events_;
30         while  (events.lNetworkEvents  !=   0 )
31          {
32            ACE_Event_Handler  * event_handler  =
33              current_info.event_handler_;
34 
35             int  reference_counting_required  =
36              event_handler -> reference_counting_policy ().value ()  ==
37              ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
38 
39             //  Call add_reference() if needed.
40             if  (reference_counting_required)
41              {
42                event_handler -> add_reference ();
43              }
44 
45             //  Upcall
46            problems  |=   this -> upcall (current_info.event_handler_,
47                                      current_info.io_handle_,
48                                      events);
49 
50             //  Call remove_reference() if needed.
51             if  (reference_counting_required)
52              {
53                event_handler -> remove_reference ();
54              }
55 
56             if  ( this -> handler_rep_.scheduled_for_deletion (slot))
57               break ;
58          }
59      }
60 
61     if  (problems  !=  ACE_Event_Handler::NULL_MASK
62         &&   ! this -> handler_rep_.scheduled_for_deletion (slot)  )
63       this -> handler_rep_.unbind (event_handle, problems);
64 
65     return   0 ;
66  }
这里值得注意的是ACE通过调用WSAEnumNetworkEvents来重置event_handle。

你可能感兴趣的:(ACE_Reactor是如何做到事件分发的)