ACE_Service_Handler类的理解和使用

来源:互联网 发布:数字移相算法 编辑:程序博客网 时间:2024/06/01 07:34

ACE_Service_Handler和ACE_Svc_Handler是类似的,不同的是使用在proactor中。
ACE_Service_Handler类从代码的接口中直接可以看到很多相关的回调,例如
handle_write_stream ,那么它们是什么时候被调的呢?看下代码:

00369 void00370 ACE_POSIX_Asynch_Write_Stream_Result::complete (size_t bytes_transferred,00371                                                 int success,00372                                                 const void *completion_key,00373                                                 u_long error)00374 {00375   // Get all the data copied.00376   this->bytes_transferred_ = bytes_transferred;00377   this->success_ = success;00378   this->completion_key_ = completion_key;00379   this->error_ = error;00380 00381   // <errno> is available in the aiocb.00382   ACE_UNUSED_ARG (error);00383 00384   // Appropriately move the pointers in the message block.00385   this->message_block_.rd_ptr (bytes_transferred);00386 00387   // Create the interface result class.00388   ACE_Asynch_Write_Stream::Result result (this);00389 00390   // Call the application handler.00391   ACE_Handler *handler = this->handler_proxy_.get ()->handler ();00392   if (handler != 0)00393     handler->handle_write_stream (result);00394 }

在上述的393行,而这里的complete的调用位置是:

00556 void00557 ACE_POSIX_Proactor::application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,00558                                                size_t bytes_transferred,00559                                                const void */* completion_key*/,00560                                                u_long error)00561 {00562   ACE_SEH_TRY00563     {00564       // Call completion hook00565       asynch_result->complete (bytes_transferred,00566                                error ? 0 : 1,00567                                0, // No completion key.00568                                error);00569     }00570   ACE_SEH_FINALLY00571     {00572       // This is crucial to prevent memory leaks00573       delete asynch_result;00574     }00575 }00576 

但是看过这个函数的调用之后,会发现无论是在windows还是posix的实现中,这个函数都再handel_events中被调用。而且这里在ACE_Proactor中,run_event_loop都是空实现,其handle_events是在proactor_run_event_loop函数中被调用的,这点尤其需要注意。

另外的一个问题是,ACE_Asynch_Connector/Acceptor《handler》这些实际处理事件的模板类,是如何将handler和proactor联系起来的?
1.先看看ACE_Proactor是何时产生的。
通过堆栈查看到,ACE_Asynch_Connector的open函数会调用其私有成员变量ACE_Asynch_Connect类型的asynch_connect_的open函数,在这个函数中会调用get_proactor接口为user获取一个proactor,ACE_Proactor的第一个实例就在这里实例化了,至于为什么ACE_Proactor的实例会是ACE_POSIX_AIOCB_Proactor,和这里的ACE_REGISTER_FRAMEWORK_COMPONENT显然脱不了干系。

00360 ACE_Proactor *00361 ACE_Proactor::instance (size_t /* threads */)00362 {00363   ACE_TRACE ("ACE_Proactor::instance");00364 00365   if (ACE_Proactor::proactor_ == 0)00366     {00367       // Perform Double-Checked Locking Optimization.00368       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,00369                                 *ACE_Static_Object_Lock::instance (),00370                                 0));00371 00372       if (ACE_Proactor::proactor_ == 0)00373         {00374           ACE_NEW_RETURN (ACE_Proactor::proactor_,00375                           ACE_Proactor,00376                           0);00377 00378           ACE_Proactor::delete_proactor_ = 1;00379           ACE_REGISTER_FRAMEWORK_COMPONENT(ACE_Proactor, ACE_Proactor::proactor_);00380         }00381     }00382   return ACE_Proactor::proactor_;

2.proactor如何和Handler绑定在一起的。需要明白的是Handler本身是有有一个proactor类型的指针专门用于保存绑定的proactor的,所以关键就是这个指针是何时填充赋值的。
在ACE_Asynch_Connector的handle_connect回调中,

00077 template <class HANDLER> void00078 ACE_Asynch_Connector<HANDLER>::handle_connect (const ACE_Asynch_Connect::Result &result)00079 {00080   // Variable for error tracking00081   int error = 0;00082 00083   // If the asynchronous connect fails.00084   if (!result.success () ||00085       result.connect_handle () == ACE_INVALID_HANDLE)00086     {00087       error = 1;00088     }00089 00090   if (result.error () != 0)00091     {00092       error = 1;00093     }00094 00095   // set blocking mode00096   if (!error &&00097       ACE::clr_flags00098         (result.connect_handle (), ACE_NONBLOCK) != 0)00099     {00100       error = 1;00101       ACE_ERROR ((LM_ERROR,00102                   ACE_LIB_TEXT ("%p\n"),00103                   ACE_LIB_TEXT ("ACE_Asynch_Connector::handle_connect : Set blocking mode")));00104     }00105 00106   // Parse the addresses.00107   ACE_INET_Addr local_address;00108   ACE_INET_Addr remote_address;00109   if (!error &&00110       (this->validate_new_connection_ || this->pass_addresses_))00111     this->parse_address (result,00112                          remote_address,00113                          local_address);00114 00115   // Call validate_connection even if there was an error - it's the only00116   // way the application can learn the connect disposition.00117   if (this->validate_new_connection_ &&00118       this->validate_connection (result, remote_address, local_address) == -1)00119     {00120       error = 1;00121     }00122 00123   HANDLER *new_handler = 0;00124   if (!error)00125     {00126       // The Template method00127       new_handler = this->make_handler ();00128       if (new_handler == 0)00129         {00130           error = 1;00131           ACE_ERROR ((LM_ERROR,00132                       ACE_LIB_TEXT ("%p\n"),00133                       ACE_LIB_TEXT ("ACE_Asynch_Connector::handle_connect : Making of new handler failed")));00134         }00135     }00136 00137   // If no errors00138   if (!error)00139     {00140       // Update the Proactor.00141       new_handler->proactor (this->proactor ());00142 00143       // Pass the addresses00144       if (this->pass_addresses_)00145         new_handler->addresses (remote_address,00146                                 local_address);00147 00148       // Pass the ACT00149       if (result.act () != 0)00150         new_handler->act (result.act ());00151 00152       // Set up the handler's new handle value00153       new_handler->handle (result.connect_handle ());00154 00155       ACE_Message_Block  mb;00156 00157       // Initiate the handler with empty message block;00158       new_handler->open (result.connect_handle (), mb);00159     }00160 00161   // On failure, no choice but to close the socket00162   if (error &&00163       result.connect_handle() != ACE_INVALID_HANDLE)00164     ACE_OS::closesocket (result.connect_handle ());00165 }

开始使用HANDLER 类型,而实际的处理器回调函数都是在HANDLER 类型中的。这里的make_handler默认实现实际也只是调用了ACE_NEW_RETURN宏,该宏只是简单的new了一个HANDLER 类型的处理器,调用了其构造函数而已。
再来看第141行,这一行很明显是将新构造的HANDLER 类型的处理器handler的和当前的proactor挂接起来。

3.那么handler的handle是如何注册到proactor中去的呢?
如果没有注册动作,显然proactor是没法检测到事件。这点需要我们手动去完成,
再上述代码的158行,说明了handler需要实现open接口,而在open接口中,有必要将ACE_Aysnch_Read_Stream和ACE_Aysnch_Write_Stream类型的对象作为handler的成员变量,并且在handler的这个open中打开即调用open。为甚?
因为ACE_Aysnch_Read/Write_Stream的open接口中,实际是调用了其基类的open即ACE_Asynch_Operation::open,其实现是调用implementation的open,将handler,handle和proactor真正的绑定,比如ACE_WIN32_Aysnch_Operation的open,就会调用ACE_WIN32_Proactor的register_handle接口,将handle注册到监听中。
换句话说,158行的代码中的handle即我们需要实际检测的handle,而其处理的handler就是调用open的handler。不过处理登记handle上的数据操作完成和实际数据处理,依赖于ACE_Message_Block ,且登记数据操作和处理数据实际上是由ACE_Aysnch_Read/Write_Stream来完成的,处理完成后的则是handler的回调。
所以这里有几个步骤:

  • 建立连接,获取handle,这是Connector的handle_connect完成的
  • 将handle加入proactor的检测队列,并将ACE_Message_Block和其绑定,用于数据处理,这是由ACE_Aysnch_Read/Write_Stream的open及相关接口完成(需要我们负责手动去完成他们的绑定即调open接口(在handler的open接口中))
  • 获取handle上处理完成,并将最终结果的ACE_Message_Block通知并进行通知处理,则是由Handler中的virtual void handle_read_stream 等回调来完成。(负责实现回调)
0 0