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 <shuston@riverace.com>
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的用法请参见前一篇我的示例。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ace技术内幕:深入解析ace架构设计与实现原理》从构架模式、编程示例和源代码3个维度系统地对经典网络框架ace(adaptivemunicationenvironment)的架构设计和实现原理进行了深入分析,它能解决4个方面的问题:,帮助框架设计者领略软件框架设计的普适原则和思想,进而设计出自己的软件框架;第二,帮助ace应用开发人员加深对ace框架的理解,提升开发水平,更好地去定制和扩展ace框架,以及解决c 网络通信中的难题;第三,帮助c 开发人员加深c 语言功底,书中有大量对c 源代码的分析,包括网络编程、动态库编程和异步编程等,还涉及10余个经典的设计模式的解析;第四,增强平台开发人员和软件架构师的技术修养,ace的设计和实现都极其,它的实现源码和架构思想非常值得去学习和研究。 全书一共7章,详细分析了acereactor、serviceconfigurator、task、acceptor_connector、proactor和streams等6个框架的架构设计与实现原理。每个框架的分析分为3部分:,框架的设计分析,每个框架(除task框架)都有一个构架模式与之对应,构架模式阐述了框架的设计原理,给出了框架的总体结构,是学习框架的理论基础;第二,框架的应用分析,每个框架都有一个应用实例与之对应,应用实例既帮助读者了解框架的使用方法,又为读者提供了一个可以调试的应用程序,便于读者使用调试器探索框架的内部秘密;第三,框架的实现分析,这是本书的重点,对框架的实现原理进行了详细的分析,并且对重点的类和流程给出了uml类图和uml顺序图,可以让读者在短时间内掌握框架的实现技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值