Select_Reactor_Base.h

Go to the documentation of this file.
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 */

Generated on Thu Nov 9 09:42:02 2006 for ACE by doxygen 1.3.6