PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/acelite/ace/TP_Reactor.h

https://github.com/Bootz/Singularity
C Header | 320 lines | 103 code | 59 blank | 158 comment | 0 complexity | f85145bb82eddea839ce7b28b3279f82 MD5 | raw file
  1. // -*- C++ -*-
  2. //=============================================================================
  3. /**
  4. * @file TP_Reactor.h
  5. *
  6. * $Id: TP_Reactor.h 82723 2008-09-16 09:35:44Z johnnyw $
  7. *
  8. * The ACE_TP_Reactor (aka, Thread Pool Reactor) uses the
  9. * Leader/Followers pattern to demultiplex events among a pool of
  10. * threads. When using a thread pool reactor, an application
  11. * pre-spawns a fixed number of threads. When these threads
  12. * invoke the ACE_TP_Reactor's handle_events() method, one thread
  13. * will become the leader and wait for an event. The other
  14. * follower threads will queue up waiting for their turn to become
  15. * the leader. When an event occurs, the leader will pick a
  16. * follower to become the leader and go on to handle the event.
  17. * The consequence of using ACE_TP_Reactor is the amortization of
  18. * the costs used to create threads. The context switching cost
  19. * will also reduce. Moreover, the total resources used by
  20. * threads are bounded because there are a fixed number of threads.
  21. *
  22. * @author Irfan Pyarali <irfan@cs.wustl.edu>
  23. * @author Nanbor Wang <nanbor@cs.wustl.edu>
  24. */
  25. //=============================================================================
  26. #ifndef ACE_TP_REACTOR_H
  27. #define ACE_TP_REACTOR_H
  28. #include /**/ "ace/pre.h"
  29. #include "ace/Select_Reactor.h"
  30. #include "ace/Timer_Queue.h" /* Simple forward decl won't work... */
  31. #if !defined (ACE_LACKS_PRAGMA_ONCE)
  32. # pragma once
  33. #endif /* ACE_LACKS_PRAGMA_ONCE */
  34. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  35. /**
  36. * @class ACE_EH_Dispatch_Info
  37. *
  38. * @brief This structure contains information of the activated event
  39. * handler.
  40. */
  41. class ACE_EH_Dispatch_Info
  42. {
  43. public:
  44. ACE_EH_Dispatch_Info (void);
  45. void set (ACE_HANDLE handle,
  46. ACE_Event_Handler *event_handler,
  47. ACE_Reactor_Mask mask,
  48. ACE_EH_PTMF callback);
  49. bool dispatch (void) const;
  50. ACE_HANDLE handle_;
  51. ACE_Event_Handler *event_handler_;
  52. ACE_Reactor_Mask mask_;
  53. ACE_EH_PTMF callback_;
  54. int resume_flag_;
  55. bool reference_counting_required_;
  56. private:
  57. bool dispatch_;
  58. // Disallow copying and assignment.
  59. ACE_EH_Dispatch_Info (const ACE_EH_Dispatch_Info &);
  60. ACE_EH_Dispatch_Info &operator= (const ACE_EH_Dispatch_Info &);
  61. };
  62. /**
  63. * @class ACE_TP_Token_Guard
  64. *
  65. * @brief A helper class that helps grabbing, releasing and waiting
  66. * on tokens for a thread that tries calling handle_events ().
  67. *
  68. * In short, this class will be owned by one thread by creating on the
  69. * stack. This class gives the status of the ownership of the token
  70. * and manages the ownership
  71. */
  72. class ACE_TP_Token_Guard
  73. {
  74. public:
  75. /// Constructor that will grab the token for us
  76. ACE_TP_Token_Guard (ACE_Select_Reactor_Token &token);
  77. /// Destructor. This will release the token if it hasnt been
  78. /// released till this point
  79. ~ACE_TP_Token_Guard (void);
  80. /// Release the token ..
  81. void release_token (void);
  82. /// Returns whether the thread that created this object ownes the
  83. /// token or not.
  84. bool is_owner (void);
  85. /// A helper method that grabs the token for us, after which the
  86. /// thread that owns that can do some actual work.
  87. int acquire_read_token (ACE_Time_Value *max_wait_time = 0);
  88. /**
  89. * A helper method that grabs the token for us, after which the
  90. * thread that owns that can do some actual work. This differs from
  91. * acquire_read_token() as it uses acquire () to get the token instead of
  92. * acquire_read ()
  93. */
  94. int acquire_token (ACE_Time_Value *max_wait_time = 0);
  95. private:
  96. // Disallow default construction.
  97. ACE_TP_Token_Guard (void);
  98. // Disallow copying and assignment.
  99. ACE_TP_Token_Guard (const ACE_TP_Token_Guard &);
  100. ACE_TP_Token_Guard &operator= (const ACE_TP_Token_Guard &);
  101. private:
  102. /// The Select Reactor token.
  103. ACE_Select_Reactor_Token &token_;
  104. /// Flag that indicate whether the thread that created this object
  105. /// owns the token or not. A value of false indicates that this class
  106. /// hasnt got the token (and hence the thread) and a value of true
  107. /// vice-versa.
  108. bool owner_;
  109. };
  110. /**
  111. * @class ACE_TP_Reactor
  112. *
  113. * @brief Specialization of ACE_Select_Reactor to support thread-pool
  114. * based event dispatching.
  115. *
  116. * One of the shortcomings of the ACE_Select_Reactor is that it
  117. * does not support a thread pool-based event dispatching model,
  118. * similar to the one in ACE_WFMO_Reactor. In ACE_Select_Reactor, only
  119. * thread can call handle_events() at any given time. ACE_TP_Reactor
  120. * removes this short-coming.
  121. *
  122. * ACE_TP_Reactor is a specialization of ACE_Select_Reactor to support
  123. * thread pool-based event dispatching. This reactor takes advantage
  124. * of the fact that events reported by @c select() are persistent if not
  125. * acted upon immediately. It works by remembering the event handler
  126. * which was just activated, suspending it for further I/O activities,
  127. * releasing the internal lock (so that another thread can start waiting
  128. * in the event loop) and then dispatching the event's handler outside the
  129. * scope of the reactor lock. After the event handler has been dispatched
  130. * the event handler is resumed for further I/O activity.
  131. *
  132. * This reactor implementation is best suited for situations when the
  133. * callbacks to event handlers can take arbitrarily long and/or a number
  134. * of threads are available to run the event loop. Note that I/O-processing
  135. * callback code in event handlers (e.g. handle_input()) does not have to
  136. * be modified or made thread-safe for this reactor. This is because
  137. * before an I/O event is dispatched to an event handler, the handler is
  138. * suspended; it is resumed by the reactor after the upcall completes.
  139. * Therefore, multiple I/O events will not be made to one event handler
  140. * multiple threads simultaneously. This suspend/resume protection does not
  141. * apply to either timers scheduled with the reactor or to notifications
  142. * requested via the reactor. When using timers and/or notifications you
  143. * must provide proper protection for your class in the context of multiple
  144. * threads.
  145. */
  146. class ACE_Export ACE_TP_Reactor : public ACE_Select_Reactor
  147. {
  148. public:
  149. /// Initialize ACE_TP_Reactor with the default size.
  150. ACE_TP_Reactor (ACE_Sig_Handler * = 0,
  151. ACE_Timer_Queue * = 0,
  152. bool mask_signals = true,
  153. int s_queue = ACE_Select_Reactor_Token::FIFO);
  154. /**
  155. * Initialize the ACE_TP_Reactor to manage
  156. * @a max_number_of_handles. If @a restart is non-0 then the
  157. * ACE_Reactor's @c handle_events() method will be restarted
  158. * automatically when @c EINTR occurs. If @a sh or
  159. * @a tq are non-0 they are used as the signal handler and
  160. * timer queue, respectively.
  161. */
  162. ACE_TP_Reactor (size_t max_number_of_handles,
  163. bool restart = false,
  164. ACE_Sig_Handler *sh = 0,
  165. ACE_Timer_Queue *tq = 0,
  166. bool mask_signals = true,
  167. int s_queue = ACE_Select_Reactor_Token::FIFO);
  168. /**
  169. * This event loop driver that blocks for @a max_wait_time before
  170. * returning. It will return earlier if timer events, I/O events,
  171. * or signal events occur. Note that @a max_wait_time can be 0, in
  172. * which case this method blocks indefinitely until events occur.
  173. *
  174. * @a max_wait_time is decremented to reflect how much time this call
  175. * took. For instance, if a time value of 3 seconds is passed to
  176. * handle_events and an event occurs after 2 seconds,
  177. * @a max_wait_time will equal 1 second. This can be used if an
  178. * application wishes to handle events for some fixed amount of
  179. * time.
  180. *
  181. * @return The total number of events that were dispatched; 0 if the
  182. * @a max_wait_time elapsed without dispatching any handlers, or -1
  183. * if an error occurs (check @c errno for more information).
  184. */
  185. virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
  186. virtual int handle_events (ACE_Time_Value &max_wait_time);
  187. /// Does the reactor allow the application to resume the handle on
  188. /// its own ie. can it pass on the control of handle resumption to
  189. /// the application. The TP reactor has can allow applications to
  190. /// resume handles. So return a positive value.
  191. virtual int resumable_handler (void);
  192. /// Called from handle events
  193. static void no_op_sleep_hook (void *);
  194. /// The ACE_TP_Reactor implementation does not have a single owner thread.
  195. /// Attempts to set the owner explicitly are ignored. The reported owner
  196. /// thread is the current Leader in the pattern.
  197. virtual int owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0);
  198. /// Return the thread ID of the current Leader.
  199. virtual int owner (ACE_thread_t *t_id);
  200. /// Declare the dynamic allocation hooks.
  201. ACE_ALLOC_HOOK_DECLARE;
  202. protected:
  203. // = Internal methods that do the actual work.
  204. /// Template method from the base class.
  205. virtual void clear_dispatch_mask (ACE_HANDLE handle,
  206. ACE_Reactor_Mask mask);
  207. /// Dispatch just 1 signal, timer, notification handlers
  208. int dispatch_i (ACE_Time_Value *max_wait_time,
  209. ACE_TP_Token_Guard &guard);
  210. /// Get the event that needs dispatching. It could be either a
  211. /// signal, timer, notification handlers or return possibly 1 I/O
  212. /// handler for dispatching. In the most common use case, this would
  213. /// return 1 I/O handler for dispatching
  214. int get_event_for_dispatching (ACE_Time_Value *max_wait_time);
  215. #if 0
  216. // @Ciju
  217. // signal handling isn't in a production state yet.
  218. // Commenting it out for now.
  219. /// Method to handle signals
  220. /// @note It is just busted at this point in time.
  221. int handle_signals (int &event_count,
  222. ACE_TP_Token_Guard &g);
  223. #endif // #if 0
  224. /// Handle timer events
  225. int handle_timer_events (int &event_count,
  226. ACE_TP_Token_Guard &g);
  227. /// Handle notify events
  228. int handle_notify_events (int &event_count,
  229. ACE_TP_Token_Guard &g);
  230. /// handle socket events
  231. int handle_socket_events (int &event_count,
  232. ACE_TP_Token_Guard &g);
  233. /// This method shouldn't get called.
  234. virtual void notify_handle (ACE_HANDLE handle,
  235. ACE_Reactor_Mask mask,
  236. ACE_Handle_Set &,
  237. ACE_Event_Handler *eh,
  238. ACE_EH_PTMF callback);
  239. private:
  240. /// Get the handle of the notify pipe from the ready set if there is
  241. /// an event in the notify pipe.
  242. ACE_HANDLE get_notify_handle (void);
  243. /// Get socket event dispatch information.
  244. int get_socket_event_info (ACE_EH_Dispatch_Info &info);
  245. /// Notify the appropriate <callback> in the context of the <eh>
  246. /// associated with <handle> that a particular event has occurred.
  247. int dispatch_socket_event (ACE_EH_Dispatch_Info &dispatch_info);
  248. /// Clear the @a handle from the read_set
  249. void clear_handle_read_set (ACE_HANDLE handle);
  250. int post_process_socket_event (ACE_EH_Dispatch_Info &dispatch_info,int status);
  251. private:
  252. /// Deny access since member-wise won't work...
  253. ACE_TP_Reactor (const ACE_TP_Reactor &);
  254. ACE_TP_Reactor &operator = (const ACE_TP_Reactor &);
  255. };
  256. ACE_END_VERSIONED_NAMESPACE_DECL
  257. #if defined (__ACE_INLINE__)
  258. #include "ace/TP_Reactor.inl"
  259. #endif /* __ACE_INLINE__ */
  260. #include /**/ "ace/post.h"
  261. #endif /* ACE_TP_REACTOR_H */