Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Select_Reactor_Base.h

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

Generated on Mon Jun 16 11:21:08 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002