歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 在ACE中使用epoll的ET模式

在ACE中使用epoll的ET模式

日期:2017/3/1 11:00:45   编辑:Linux編程

用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. int register_handler_i (ACE_HANDLE handle,ACE_Event_Handler *eh,ACE_Reactor_Mask mask)
  6. {
  7. ACE_TRACE ("ACE_Dev_Poll_Reactor::register_handler_i");
  8. if (handle == ACE_INVALID_HANDLE
  9. || mask == ACE_Event_Handler::NULL_MASK)
  10. {
  11. errno = EINVAL;
  12. return -1;
  13. }
  14. if (this->handler_rep_.find (handle) == 0)
  15. {
  16. // Handler not present in the repository. Bind it.
  17. if (this->handler_rep_.bind (handle, event_handler, mask) != 0)
  18. return -1;
  19. struct epoll_event epev;
  20. ACE_OS::memset (&epev, 0, sizeof (epev));
  21. static const int op = EPOLL_CTL_ADD;
  22. epev.events = this->reactor_mask_to_poll_event (mask);
  23. epev.data.fd = handle;
  24. if( NET_SETTING.ET_MODE )
  25. {
  26. epev.events |= EPOLLET; // 關鍵代碼,增加ET標識 [1/13/2011 yao]
  27. }
  28. if (::epoll_ctl (this->poll_fd_, op, handle, &epev) == -1)
  29. {
  30. ACE_ERROR ((LM_ERROR, "%p\n", "epoll_ctl"));
  31. (void) this->handler_rep_.unbind (handle);
  32. return -1;
  33. }
  34. }
  35. else
  36. {
  37. // Handler is already present in the repository, so register it
  38. // again, possibly for different event. Add new mask to the
  39. // current one.
  40. if (this->mask_ops_i (handle, mask, ACE_Reactor::ADD_MASK) == -1)
  41. ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "mask_ops_i"), -1);
  42. }
  43. // Note the fact that we've changed the state of the wait_set_,
  44. // which is used by the dispatching loop to determine whether it can
  45. // keep going or if it needs to reconsult select().
  46. // this->state_changed_ = 1;
  47. return 0;
  48. }
  49. ....
  50. }

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

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

Copyright © Linux教程網 All Rights Reserved