00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Select_Reactor_Base.h 00006 * 00007 * Select_Reactor_Base.h,v 4.49 2006/03/13 15:11:03 jwillemsen Exp 00008 * 00009 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef ACE_SELECT_REACTOR_BASE_H 00014 #define ACE_SELECT_REACTOR_BASE_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include "ace/Timer_Queuefwd.h" 00019 00020 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00021 # pragma once 00022 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00023 00024 #include "ace/Event_Handler.h" 00025 #include "ace/Handle_Set.h" 00026 #include "ace/Pipe.h" 00027 #include "ace/Reactor_Impl.h" 00028 00029 #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE) 00030 # include "ace/Unbounded_Queue.h" 00031 #endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */ 00032 00033 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00034 00035 // Add useful typedefs to simplify the following code. 00036 typedef void (ACE_Handle_Set::*ACE_FDS_PTMF) (ACE_HANDLE); 00037 typedef int (ACE_Event_Handler::*ACE_EH_PTMF) (ACE_HANDLE); 00038 00039 // Forward declaration. 00040 class ACE_Select_Reactor_Impl; 00041 class ACE_Sig_Handler; 00042 00043 /* 00044 * Hook to specialize the Select_Reactor_Base implementation 00045 * with the concrete reactor, e.g., select or tp reactor 00046 * specified at build/compilation time. 00047 */ 00048 //@@ REACTOR_SPL_INCLUDE_FORWARD_DECL_ADD_HOOK 00049 00050 /** 00051 * @class ACE_Select_Reactor_Handle_Set 00052 * 00053 * @brief Track handles we are interested for various events. 00054 */ 00055 class ACE_Export ACE_Select_Reactor_Handle_Set 00056 { 00057 public: 00058 /// Read events (e.g., input pending, accept pending). 00059 ACE_Handle_Set rd_mask_; 00060 00061 /// Write events (e.g., flow control abated, non-blocking connection 00062 /// complete). 00063 ACE_Handle_Set wr_mask_; 00064 00065 /// Exception events (e.g., SIG_URG). 00066 ACE_Handle_Set ex_mask_; 00067 }; 00068 00069 /** 00070 * @class ACE_Event_Tuple 00071 * 00072 * @brief An ACE_Event_Handler and its associated ACE_HANDLE. 00073 * 00074 * One ACE_Event_Handler is registered for one or more 00075 * ACE_HANDLE. At various points, this information must be 00076 * stored explicitly. This class provides a lightweight 00077 * mechanism to do so. 00078 */ 00079 class ACE_Export ACE_Event_Tuple 00080 { 00081 public: 00082 /// Default constructor. 00083 ACE_Event_Tuple (void); 00084 00085 /// Constructor. 00086 ACE_Event_Tuple (ACE_Event_Handler *eh, 00087 ACE_HANDLE h); 00088 00089 /// Destructor. 00090 ~ACE_Event_Tuple (void); 00091 00092 /// Equality operator. 00093 bool operator== (const ACE_Event_Tuple &rhs) const; 00094 00095 /// Inequality operator. 00096 bool operator!= (const ACE_Event_Tuple &rhs) const; 00097 00098 /// Handle. 00099 ACE_HANDLE handle_; 00100 00101 /// ACE_Event_Handler associated with the ACE_HANDLE. 00102 ACE_Event_Handler *event_handler_; 00103 }; 00104 00105 /** 00106 * @class ACE_Select_Reactor_Notify 00107 * 00108 * @brief Unblock the ACE_Select_Reactor from its event loop. 00109 * 00110 * This implementation is necessary for cases where the 00111 * ACE_Select_Reactor is run in a multi-threaded program. In 00112 * this case, we need to be able to unblock @c select or @c poll 00113 * when updates occur other than in the main 00114 * ACE_Select_Reactor thread. To do this, we signal an 00115 * auto-reset event the ACE_Select_Reactor is listening on. 00116 * If an ACE_Event_Handler and ACE_Select_Reactor_Mask is 00117 * passed to @c notify, the appropriate @c handle_* method is 00118 * dispatched in the context of the ACE_Select_Reactor thread. 00119 */ 00120 class ACE_Export ACE_Select_Reactor_Notify : public ACE_Reactor_Notify 00121 { 00122 public: 00123 /// Constructor. 00124 ACE_Select_Reactor_Notify (void); 00125 00126 /// Destructor. 00127 virtual ~ACE_Select_Reactor_Notify (void); 00128 00129 // = Initialization and termination methods. 00130 /// Initialize. 00131 virtual int open (ACE_Reactor_Impl *, 00132 ACE_Timer_Queue * = 0, 00133 int disable_notify_pipe = 0); 00134 00135 /// Destroy. 00136 virtual int close (void); 00137 00138 /** 00139 * Called by a thread when it wants to unblock the 00140 * ACE_Select_Reactor. This wakeups the ACE_Select_Reactor if 00141 * currently blocked in @c select/poll. Pass over both the 00142 * @c Event_Handler *and* the @c mask to allow the caller to dictate 00143 * which @c Event_Handler method the ACE_Select_Reactor will 00144 * invoke. The ACE_Time_Value indicates how long to blocking 00145 * trying to notify the ACE_Select_Reactor. If @a timeout == 0, 00146 * the caller will block until action is possible, else will wait 00147 * until the relative time specified in @c *timeout elapses). 00148 */ 00149 virtual int notify (ACE_Event_Handler * = 0, 00150 ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK, 00151 ACE_Time_Value * timeout = 0); 00152 00153 /// Handles pending threads (if any) that are waiting to unblock the 00154 /// ACE_Select_Reactor. 00155 virtual int dispatch_notifications (int &number_of_active_handles, 00156 ACE_Handle_Set &rd_mask); 00157 00158 /// Returns the ACE_HANDLE of the notify pipe on which the reactor 00159 /// is listening for notifications so that other threads can unblock 00160 /// the Select_Reactor 00161 virtual ACE_HANDLE notify_handle (void); 00162 00163 /// Handle one of the notify call on the @c handle. This could be 00164 /// because of a thread trying to unblock the <Reactor_Impl> 00165 virtual int dispatch_notify (ACE_Notification_Buffer &buffer); 00166 00167 /// Read one of the notify call on the @a handle into the 00168 /// @a buffer. This could be because of a thread trying to unblock 00169 /// the <Reactor_Impl> 00170 virtual int read_notify_pipe (ACE_HANDLE handle, 00171 ACE_Notification_Buffer &buffer); 00172 00173 /// Verify whether the buffer has dispatchable info or not. 00174 virtual int is_dispatchable (ACE_Notification_Buffer &buffer); 00175 00176 /// Called back by the ACE_Select_Reactor when a thread wants to 00177 /// unblock us. 00178 virtual int handle_input (ACE_HANDLE handle); 00179 00180 /** 00181 * Set the maximum number of times that the 00182 * <ACE_Select_Reactor_Notify::handle_input> method will iterate and 00183 * dispatch the <ACE_Event_Handlers> that are passed in via the 00184 * notify pipe before breaking out of its <recv> loop. By default, 00185 * this is set to -1, which means "iterate until the pipe is empty." 00186 * Setting this to a value like "1 or 2" will increase "fairness" 00187 * (and thus prevent starvation) at the expense of slightly higher 00188 * dispatching overhead. 00189 */ 00190 virtual void max_notify_iterations (int); 00191 00192 /** 00193 * Get the maximum number of times that the 00194 * <ACE_Select_Reactor_Notify::handle_input> method will iterate and 00195 * dispatch the <ACE_Event_Handlers> that are passed in via the 00196 * notify pipe before breaking out of its <recv> loop. 00197 */ 00198 virtual int max_notify_iterations (void); 00199 00200 /** 00201 * Purge any notifications pending in this reactor for the specified 00202 * ACE_Event_Handler object. If @a eh == 0, all notifications for all 00203 * handlers are removed (but not any notifications posted just to wake up 00204 * the reactor itself). Returns the number of notifications purged. 00205 * Returns -1 on error. 00206 */ 00207 virtual int purge_pending_notifications ( 00208 ACE_Event_Handler *sh, 00209 ACE_Reactor_Mask mask = ACE_Event_Handler::ALL_EVENTS_MASK); 00210 00211 /// Dump the state of an object. 00212 virtual void dump (void) const; 00213 00214 /// Declare the dynamic allocation hooks. 00215 ACE_ALLOC_HOOK_DECLARE; 00216 00217 protected: 00218 /** 00219 * Keep a back pointer to the ACE_Select_Reactor. If this value 00220 * if NULL then the ACE_Select_Reactor has been initialized with 00221 * <disable_notify_pipe>. 00222 */ 00223 ACE_Select_Reactor_Impl *select_reactor_; 00224 00225 /** 00226 * Contains the ACE_HANDLE the ACE_Select_Reactor is listening 00227 * on, as well as the ACE_HANDLE that threads wanting the 00228 * attention of the ACE_Select_Reactor will write to. 00229 */ 00230 ACE_Pipe notification_pipe_; 00231 00232 /** 00233 * Keeps track of the maximum number of times that the 00234 * <ACE_Select_Reactor_Notify::handle_input> method will iterate and 00235 * dispatch the <ACE_Event_Handlers> that are passed in via the 00236 * notify pipe before breaking out of its <recv> loop. By default, 00237 * this is set to -1, which means "iterate until the pipe is empty." 00238 */ 00239 int max_notify_iterations_; 00240 00241 #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE) 00242 // = This configuration queues up notifications in separate buffers that 00243 // are in user-space, rather than stored in a pipe in the OS 00244 // kernel. The kernel-level notifications are used only to trigger 00245 // the Reactor to check its notification queue. This enables many 00246 // more notifications to be stored than would otherwise be the case. 00247 00248 /// Keeps track of allocated arrays of type 00249 /// <ACE_Notification_Buffer>. 00250 ACE_Unbounded_Queue <ACE_Notification_Buffer *> alloc_queue_; 00251 00252 /// Keeps track of all pending notifications. 00253 ACE_Unbounded_Queue <ACE_Notification_Buffer *> notify_queue_; 00254 00255 /// Keeps track of all free buffers. 00256 ACE_Unbounded_Queue <ACE_Notification_Buffer *> free_queue_; 00257 00258 /// Synchronization for handling of queues. 00259 ACE_SYNCH_MUTEX notify_queue_lock_; 00260 #endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */ 00261 }; 00262 00263 /** 00264 * @class ACE_Select_Reactor_Handler_Repository 00265 * 00266 * @brief Used to map ACE_HANDLEs onto the appropriate 00267 * ACE_Event_Handler *. 00268 * 00269 * This class is necessary to shield differences between UNIX 00270 * and Win32. In UNIX, ACE_HANDLE is an int, whereas in Win32 00271 * it's a void *. This class hides all these details from the 00272 * bulk of the ACE_Select_Reactor code. All of these methods 00273 * are called with the main <Select_Reactor> token lock held. 00274 */ 00275 class ACE_Export ACE_Select_Reactor_Handler_Repository 00276 { 00277 public: 00278 friend class ACE_Select_Reactor_Handler_Repository_Iterator; 00279 00280 // = Initialization and termination methods. 00281 /// Default "do-nothing" constructor. 00282 ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor_Impl &); 00283 00284 /// Destructor. 00285 ~ACE_Select_Reactor_Handler_Repository (void); 00286 00287 /// Initialize a repository of the appropriate <size>. 00288 /** 00289 * On Unix platforms, the size parameter should be as large as the 00290 * maximum number of file descriptors allowed for a given process. 00291 * This is necessary since a file descriptor is used to directly 00292 * index the array of event handlers maintained by the Reactor's 00293 * handler repository. Direct indexing is used for efficiency 00294 * reasons. 00295 */ 00296 int open (size_t size); 00297 00298 /// Close down the repository. 00299 int close (void); 00300 00301 // = Search structure operations. 00302 00303 /** 00304 * Return the <ACE_Event_Handler *> associated with ACE_HANDLE. 00305 * If <index_p> is non-0, then return the index location of the 00306 * <handle>, if found. 00307 */ 00308 ACE_Event_Handler *find (ACE_HANDLE handle, size_t *index_p = 0); 00309 00310 /// Bind the ACE_Event_Handler * to the ACE_HANDLE with the 00311 /// appropriate ACE_Reactor_Mask settings. 00312 int bind (ACE_HANDLE, 00313 ACE_Event_Handler *, 00314 ACE_Reactor_Mask); 00315 00316 /// Remove the binding of ACE_HANDLE in accordance with the @a mask. 00317 int unbind (ACE_HANDLE, 00318 ACE_Reactor_Mask mask); 00319 00320 /// Remove all the <ACE_HANDLE, ACE_Event_Handler> tuples. 00321 int unbind_all (void); 00322 00323 // = Sanity checking. 00324 00325 // Check the <handle> to make sure it's a valid ACE_HANDLE that 00326 // within the range of legal handles (i.e., >= 0 && < max_size_). 00327 int invalid_handle (ACE_HANDLE handle); 00328 00329 // Check the <handle> to make sure it's a valid ACE_HANDLE that 00330 // within the range of currently registered handles (i.e., >= 0 && < 00331 // max_handlep1_). 00332 int handle_in_range (ACE_HANDLE handle); 00333 00334 // = Accessors. 00335 /// Returns the current table size. 00336 size_t size (void) const; 00337 00338 /// Maximum ACE_HANDLE value, plus 1. 00339 size_t max_handlep1 (void); 00340 00341 /// Dump the state of an object. 00342 void dump (void) const; 00343 00344 /// Declare the dynamic allocation hooks. 00345 ACE_ALLOC_HOOK_DECLARE; 00346 00347 private: 00348 /// Reference to our <Select_Reactor>. 00349 ACE_Select_Reactor_Impl &select_reactor_; 00350 00351 /// Maximum number of handles. 00352 ssize_t max_size_; 00353 00354 /// The highest currently active handle, plus 1 (ranges between 0 and 00355 /// <max_size_>. 00356 int max_handlep1_; 00357 00358 #if defined (ACE_WIN32) 00359 // = The mapping from <HANDLES> to <Event_Handlers>. 00360 00361 /** 00362 * The NT version implements this via a dynamically allocated 00363 * array of <ACE_Event_Tuple *>. Since NT implements ACE_HANDLE 00364 * as a void * we can't directly index into this array. Therefore, 00365 * we just do a linear search (for now). Next, we'll modify 00366 * things to use hashing or something faster... 00367 */ 00368 ACE_Event_Tuple *event_handlers_; 00369 #else 00370 /** 00371 * The UNIX version implements this via a dynamically allocated 00372 * array of <ACE_Event_Handler *> that is indexed directly using 00373 * the ACE_HANDLE value. 00374 */ 00375 ACE_Event_Handler **event_handlers_; 00376 #endif /* ACE_WIN32 */ 00377 }; 00378 00379 /** 00380 * @class ACE_Select_Reactor_Handler_Repository_Iterator 00381 * 00382 * @brief Iterate through the ACE_Select_Reactor_Handler_Repository. 00383 */ 00384 class ACE_Export ACE_Select_Reactor_Handler_Repository_Iterator 00385 { 00386 public: 00387 // = Initialization method. 00388 ACE_Select_Reactor_Handler_Repository_Iterator (const ACE_Select_Reactor_Handler_Repository *s); 00389 00390 /// dtor. 00391 ~ACE_Select_Reactor_Handler_Repository_Iterator (void); 00392 00393 // = Iteration methods. 00394 00395 /// Pass back the <next_item> that hasn't been seen in the Set. 00396 /// Returns 0 when all items have been seen, else 1. 00397 int next (ACE_Event_Handler *&next_item); 00398 00399 /// Returns 1 when all items have been seen, else 0. 00400 int done (void) const; 00401 00402 /// Move forward by one element in the set. Returns 0 when all the 00403 /// items in the set have been seen, else 1. 00404 int advance (void); 00405 00406 /// Dump the state of an object. 00407 void dump (void) const; 00408 00409 /// Declare the dynamic allocation hooks. 00410 ACE_ALLOC_HOOK_DECLARE; 00411 00412 private: 00413 /// Reference to the Handler_Repository we are iterating over. 00414 const ACE_Select_Reactor_Handler_Repository *rep_; 00415 00416 /// Pointer to the current iteration level. 00417 ssize_t current_; 00418 }; 00419 00420 /** 00421 * @class ACE_Select_Reactor_Impl 00422 * 00423 * @brief This class simply defines how Select_Reactor's basic interface 00424 * functions should look like and provides a common base class for 00425 * <Select_Reactor> using various locking mechanism. 00426 */ 00427 class ACE_Export ACE_Select_Reactor_Impl : public ACE_Reactor_Impl 00428 { 00429 public: 00430 enum 00431 { 00432 /// Default size of the Select_Reactor's handle table. 00433 DEFAULT_SIZE = ACE_DEFAULT_SELECT_REACTOR_SIZE 00434 }; 00435 00436 /// Constructor. 00437 ACE_Select_Reactor_Impl (bool mask_signals = true); 00438 00439 friend class ACE_Select_Reactor_Notify; 00440 friend class ACE_Select_Reactor_Handler_Repository; 00441 00442 /** 00443 * Purge any notifications pending in this reactor for the specified 00444 * ACE_Event_Handler object. Returns the number of notifications 00445 * purged. Returns -1 on error. 00446 */ 00447 virtual int purge_pending_notifications (ACE_Event_Handler * = 0, 00448 ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); 00449 00450 /// Does the reactor allow the application to resume the handle on 00451 /// its own ie. can it pass on the control of handle resumption to 00452 /// the application. The select reactor has no handlers that can be 00453 /// resumed by the application. So return 0; 00454 virtual int resumable_handler (void); 00455 00456 /* 00457 * Hook to add concrete methods required to specialize the 00458 * implementation with concrete methods required for the concrete 00459 * reactor implementation, for example, select, tp reactors. 00460 */ 00461 //@@ REACTOR_SPL_PUBLIC_METHODS_ADD_HOOK 00462 00463 protected: 00464 /// Allow manipulation of the <wait_set_> mask and <ready_set_> mask. 00465 virtual int bit_ops (ACE_HANDLE handle, 00466 ACE_Reactor_Mask mask, 00467 ACE_Select_Reactor_Handle_Set &handle_set, 00468 int ops); 00469 00470 /// Enqueue ourselves into the list of waiting threads at the 00471 /// appropriate point specified by <requeue_position_>. 00472 virtual void renew (void) = 0; 00473 00474 /// Check to see if the <Event_Handler> associated with @a handle is 00475 /// suspended. Returns 0 if not, 1 if so. 00476 virtual int is_suspended_i (ACE_HANDLE handle) = 0; 00477 00478 /// When register/unregister occur, then we need to re-eval our 00479 /// wait/suspend/dispatch set. 00480 virtual void clear_dispatch_mask (ACE_HANDLE handle, 00481 ACE_Reactor_Mask mask); 00482 00483 /// Table that maps <ACE_HANDLEs> to <ACE_Event_Handler *>'s. 00484 ACE_Select_Reactor_Handler_Repository handler_rep_; 00485 00486 /// Tracks handles that are ready for dispatch from <select> 00487 ACE_Select_Reactor_Handle_Set dispatch_set_; 00488 00489 /// Tracks handles that are waited for by <select>. 00490 ACE_Select_Reactor_Handle_Set wait_set_; 00491 00492 /// Tracks handles that are currently suspended. 00493 ACE_Select_Reactor_Handle_Set suspend_set_; 00494 00495 /// Track HANDLES we are interested in for various events that must 00496 /// be dispatched *without* going through <select>. 00497 ACE_Select_Reactor_Handle_Set ready_set_; 00498 00499 /// Defined as a pointer to allow overriding by derived classes... 00500 ACE_Timer_Queue *timer_queue_; 00501 00502 /// Handle signals without requiring global/static variables. 00503 ACE_Sig_Handler *signal_handler_; 00504 00505 /// Callback object that unblocks the ACE_Select_Reactor if it's 00506 /// sleeping. 00507 ACE_Reactor_Notify *notify_handler_; 00508 00509 /// Keeps track of whether we should delete the timer queue (if we 00510 /// didn't create it, then we don't delete it). 00511 bool delete_timer_queue_; 00512 00513 /// Keeps track of whether we should delete the signal handler (if we 00514 /// didn't create it, then we don't delete it). 00515 bool delete_signal_handler_; 00516 00517 /// Keeps track of whether we need to delete the notify handler (if 00518 /// we didn't create it, then we don't delete it). 00519 bool delete_notify_handler_; 00520 00521 /// True if we've been initialized yet... 00522 bool initialized_; 00523 00524 /// Restart the <handle_events> event-loop method automatically when 00525 /// <select> is interrupted via <EINTR>. 00526 int restart_; 00527 00528 /** 00529 * Position that the main ACE_Select_Reactor thread is requeued in 00530 * the list of waiters during a <notify> callback. If this value == 00531 * -1 we are requeued at the end of the list. Else if it's 0 then 00532 * we are requeued at the front of the list. Else if it's > 1 then 00533 * that indicates the number of waiters to skip over. 00534 */ 00535 int requeue_position_; 00536 00537 /// The original thread that created this Select_Reactor. 00538 ACE_thread_t owner_; 00539 00540 /** 00541 * True if state has changed during dispatching of 00542 * <ACE_Event_Handlers>, else false. This is used to determine 00543 * whether we need to make another trip through the 00544 * <Select_Reactor>'s <wait_for_multiple_events> loop. 00545 */ 00546 bool state_changed_; 00547 00548 /** 00549 * If 0 then the Reactor will not mask the signals during the event 00550 * dispatching. This is useful for applications that do not 00551 * register any signal handlers and want to reduce the overhead 00552 * introduce by the kernel level locks required to change the mask. 00553 */ 00554 bool mask_signals_; 00555 00556 /// Controls/access whether the notify handler should renew the 00557 /// Select_Reactor's token or not. 00558 int supress_notify_renew (void); 00559 void supress_notify_renew (int sr); 00560 00561 00562 private: 00563 00564 /// Determine whether we should renew Select_Reactor's token after handling 00565 /// the notification message. 00566 int supress_renew_; 00567 00568 /// Deny access since member-wise won't work... 00569 ACE_Select_Reactor_Impl (const ACE_Select_Reactor_Impl &); 00570 ACE_Select_Reactor_Impl &operator = (const ACE_Select_Reactor_Impl &); 00571 }; 00572 00573 ACE_END_VERSIONED_NAMESPACE_DECL 00574 00575 #if defined (__ACE_INLINE__) 00576 #include "ace/Select_Reactor_Base.inl" 00577 #endif /* __ACE_INLINE__ */ 00578 00579 #include /**/ "ace/post.h" 00580 00581 #endif /* ACE_SELECT_REACTOR_BASE_H */