• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            小明思考

            高性能服務(wù)器端計(jì)算
            posts - 70, comments - 428, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            1. ACE_Reactor的創(chuàng)建
            ctor: ACE_Reactor (ACE_Reactor_Impl *implementation = 0, int delete_implementation = 0);
            你可以自己創(chuàng)建一個(gè)ACE_Reactor
            但是大多數(shù)時(shí)候,我們都是通過調(diào)用ACE_Reactor::instance()這個(gè)靜態(tài)方法來返回唯一的實(shí)例。

            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_;
            }
            注意這點(diǎn)使用了雙檢測(cè)的機(jī)制(代碼1和2),為了提高效率,不用每次都加鎖。

            2. Impl手法的運(yùn)用
            ACE_Reactor有個(gè)成員變量 ACE_Reactor_Impl *implementation_;
            這個(gè)implementation_才是真正做事情的東西,典型的Impl手法。
            為什么要多一個(gè)這個(gè)間隔層呢,主要是為了實(shí)現(xiàn)跨平臺(tái)。
            因?yàn)椴煌钠脚_(tái)的Reactor差異很大。
            在Windows平臺(tái),實(shí)現(xiàn)這個(gè)是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的區(qū)別
            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復(fù)制到event_handle,最后通過WSAEventSelect將這個(gè)io_handle和event_handle綁定在一起了

            這個(gè)register_handle調(diào)用一般都在Event_Handler的open函數(shù)中,實(shí)現(xiàn)了注冊(cè)到Reactor中去。

            4. 等待事件
            如何檢測(cè)到要發(fā)生的socket的事件呢?比如有新的client連接,收發(fā)。ACE并不直接調(diào)用select函數(shù)來取得。
            ACE調(diào)用WaitForMultipleObjectsEx來等待事件的發(fā)生。ACE這樣做的好處是不但可以捕捉socket事件,也可以捕捉到其他事件。前面說過了每一個(gè)對(duì)應(yīng)的socket都有一個(gè)event_handle與之對(duì)應(yīng)。WaitForMultipleObjectsEx會(huì)將發(fā)生事件的socket handle的index返回。這樣ACE_Reactor就可以利用這個(gè)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.分發(fā)事件
            根據(jù)WaitForMultiObjectEx返回的slot就可以查詢到event_handler來調(diào)用用戶的處理函數(shù)了

             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通過調(diào)用WSAEnumNetworkEvents來重置event_handle。

            講的比較概要,更具體的細(xì)節(jié)請(qǐng)自己閱讀源碼。
            關(guān)于ACE_Reactor的用法請(qǐng)參見前一篇我的示例。


            Feedback

            # re: [ACE源碼分析]ACE_Reactor是如何做到事件分發(fā)的  回復(fù)  更多評(píng)論   

            2006-04-13 09:18 by Stone Jiang
            好文章,收藏
            另外,我發(fā)現(xiàn)提高blog積分的最好辦法是多評(píng)論別人.哈哈,我進(jìn)前100了.

            # re: [ACE源碼分析]ACE_Reactor是如何做到事件分發(fā)的[未登錄]  回復(fù)  更多評(píng)論   

            2007-05-10 17:39 by recorder
            // Perform Double-Checked Locking Optimization.

            以前看代碼的時(shí)候沒注意,看你文章聽到你重點(diǎn)提了提,偶看了看DC-Locking.pdf, 有所收獲。多謝
            999久久久免费国产精品播放| 精品久久久久一区二区三区| 久久久无码精品亚洲日韩京东传媒 | 久久久WWW成人免费精品| 欧美精品丝袜久久久中文字幕 | 欧洲成人午夜精品无码区久久| 91精品国产乱码久久久久久| 伊人久久免费视频| 伊人久久大香线蕉av不卡| 久久免费视频网站| 久久精品国产免费观看| 超级碰久久免费公开视频| 久久精品人妻中文系列| 久久精品国产国产精品四凭| 久久免费的精品国产V∧| 老司机午夜网站国内精品久久久久久久久 | 久久精品国产亚洲AV香蕉| 久久久久国产成人精品亚洲午夜| 国产毛片欧美毛片久久久| 久久久久亚洲AV无码专区网站| 日韩AV无码久久一区二区| 亚洲综合久久夜AV | 久久高潮一级毛片免费| 99久久国产综合精品网成人影院| 日韩精品久久久肉伦网站| 久久精品无码一区二区WWW| 日韩中文久久| 久久精品国产99久久久香蕉| 2020最新久久久视精品爱| 国产午夜久久影院| 国产精品久久久久天天影视| 亚洲va中文字幕无码久久| 国产成人久久精品一区二区三区 | 亚洲成色www久久网站夜月| 国产精品久久久久a影院| 久久亚洲色一区二区三区| 久久精品国产福利国产琪琪| 久久精品国产亚洲7777| 久久久久久国产a免费观看不卡| 久久精品国产99国产精品| 亚洲国产高清精品线久久 |