歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

在ACE中使用epoll的ET模式

用ace做了一個linux下的服務端程序,使用了ACE_Dev_Poll_Reactor。

運行後發現,當注冊了socket的讀寫事件(ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK)後,handle_output就會不停的被調用,同時cpu達到了100%。

查找原因,原來是ACE_Dev_Poll_Reactor中使用了epoll的LT模式,同時搜索代碼,也沒有發現ET相關的關鍵字。

最初的想法是修改ACE_Dev_Poll_Reactor的代碼,增加ET的處理。但是我不想修改ace庫內部的代碼,所以使用了派生的方法,同時感覺到ace結構設計的完美。

  1. class CMyReactor : public ACE_Dev_Poll_Reactor  
  2.   
  3. {  
  4.   
  5. ....  
  6.   
  7. //重載內部注冊回調的接口   
  8.   
  9. int register_handler_i (ACE_HANDLE handle,ACE_Event_Handler *eh,ACE_Reactor_Mask mask)  
  10.   
  11. {  
  12.   
  13.  ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler_i");  
  14.   
  15.  if (handle == ACE_INVALID_HANDLE  
  16.   || mask == ACE_Event_Handler::NULL_MASK)  
  17.  {  
  18.   errno = EINVAL;  
  19.   return -1;  
  20.  }  
  21.   
  22.  if (this->handler_rep_.find (handle) == 0)  
  23.  {  
  24.   // Handler not present in the repository.  Bind it.   
  25.   if (this->handler_rep_.bind (handle, event_handler, mask) != 0)  
  26.    return -1;  
  27.   
  28.   struct epoll_event epev;  
  29.   ACE_OS::memset (&epev, 0, sizeof (epev));  
  30.   static const int op = EPOLL_CTL_ADD;  
  31.   
  32.   epev.events  = this->reactor_mask_to_poll_event (mask);  
  33.   epev.data.fd = handle;  
  34.   
  35.   if( NET_SETTING.ET_MODE )  
  36.   {  
  37.    epev.events |= EPOLLET;  // 關鍵代碼,增加ET標識 [1/13/2011 yao]   
  38.   }  
  39.   
  40.   if (::epoll_ctl (this->poll_fd_, op, handle, &epev) == -1)  
  41.   {  
  42.    ACE_ERROR ((LM_ERROR, "%p\n""epoll_ctl"));  
  43.    (voidthis->handler_rep_.unbind (handle);  
  44.    return -1;  
  45.   }  
  46.  }  
  47.  else  
  48.  {  
  49.   // Handler is already present in the repository, so register it   
  50.   // again, possibly for different event.  Add new mask to the   
  51.   // current one.   
  52.   if (this->mask_ops_i (handle, mask, ACE_Reactor::ADD_MASK) == -1)  
  53.    ACE_ERROR_RETURN ((LM_ERROR, "%p\n""mask_ops_i"), -1);  
  54.  }  
  55.   
  56.  // Note the fact that we've changed the state of the wait_set_,   
  57.  // which is used by the dispatching loop to determine whether it can   
  58.  // keep going or if it needs to reconsult select().   
  59.  // this->state_changed_ = 1;   
  60.   
  61.  return 0;  
  62.   
  63.   
  64.   
  65.   
  66. }  
  67.   
  68. ....  
  69.   
  70. }  

只要在epoll_ctl 之前增加EPOLLET就可以了搞定了。

如果想要執行,還需要重載幾個其他的函數,因為register_handler_i並不是虛函數,所以要從調用register_handler_i的函數開始重載。這裡有沒有更好的做法,我還不清楚。哪位朋友有更好的做法,歡迎一起研究一下

Copyright © Linux教程網 All Rights Reserved