• [ACE源码分析]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。

  • 相关阅读:
    Orleans的深入
    Orleans的入门教程
    .net core 微服务通讯组件Orleans的使用与配置
    AddTransient、AddSingleton、AddScoped的区别
    近期做架构师的总结
    大数据分析的深度与假象
    SQL反模式-1
    学习总结---INNODB 事务并发
    Tomcat的error-page掩盖action实例化的exception
    A SQL to insert continuous values
  • 原文地址:https://www.cnblogs.com/lkskevin/p/2503490.html
Copyright © 2020-2023  润新知