Dev_Poll_Reactor.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // =========================================================================
00004 /**
00005  *  @file    Dev_Poll_Reactor.h
00006  *
00007  *  $Id: Dev_Poll_Reactor.h 80826 2008-03-04 14:51:23Z wotte $
00008  *
00009  *  @c /dev/poll (or Linux @c sys_epoll) based Reactor implementation.
00010  *
00011  *  @author  Ossama Othman <ossama@dre.vanderbilt.edu>
00012  */
00013 // =========================================================================
00014 
00015 
00016 #ifndef ACE_DEV_POLL_REACTOR_H
00017 #define ACE_DEV_POLL_REACTOR_H
00018 
00019 #include /**/ "ace/pre.h"
00020 
00021 #include /**/ "ace/ACE_export.h"
00022 
00023 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00024 # pragma once
00025 #endif /* ACE_LACKS_PRAGMA_ONCE */
00026 
00027 #if defined (ACE_HAS_EVENT_POLL) && defined (ACE_HAS_DEV_POLL)
00028 #  error ACE_HAS_EVENT_POLL and ACE_HAS_DEV_POLL are mutually exclusive.
00029 #endif  /* ACE_HAS_EVENT_POLL && defined ACE_HAS_DEV_POLL */
00030 
00031 #if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
00032 
00033 #include "ace/Pipe.h"
00034 #include "ace/Lock_Adapter_T.h"
00035 #include "ace/Reactor_Impl.h"
00036 #include "ace/Reactor_Token_T.h"
00037 #include "ace/Token.h"
00038 
00039 #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
00040 # include "ace/Notification_Queue.h"
00041 #endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
00042 
00043 #if defined (ACE_HAS_DEV_POLL)
00044 struct pollfd;
00045 #elif defined (ACE_HAS_EVENT_POLL)
00046 struct epoll_event;
00047 #endif
00048 
00049 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00050 
00051 // Forward declarations
00052 class ACE_Sig_Handler;
00053 class ACE_Dev_Poll_Reactor;
00054 
00055 /**
00056  * @class ACE_Dev_Poll_Event_Tuple
00057  *
00058  * @brief Class that associates specific event mask with a given event
00059  *        handler.
00060  *
00061  * This class merely provides a means to associate an event mask
00062  * with an event handler.  Such an association is needed since it is
00063  * not possible to retrieve the event mask from the "interest set"
00064  * stored in the `/dev/poll' or `/dev/epoll' driver.  Without this
00065  * external association, it would not be possible keep track of the
00066  * event mask for a given event handler when suspending it or resuming
00067  * it.
00068  *
00069  * @note An ACE_Handle_Set is not used since the number of handles may
00070  *       exceed its capacity (ACE_DEFAULT_SELECT_REACTOR_SIZE).
00071  */
00072 class ACE_Dev_Poll_Event_Tuple
00073 {
00074 public:
00075 
00076   /// Constructor.
00077   ACE_Dev_Poll_Event_Tuple (void);
00078 
00079 public:
00080 
00081   /// The event handler.
00082   ACE_Event_Handler *event_handler;
00083 
00084   /// The event mask for the above event handler.
00085   ACE_Reactor_Mask mask;
00086 
00087   /// Flag that states whether or not the event handler is suspended.
00088   char suspended;
00089 };
00090 
00091 // ---------------------------------------------------------------------
00092 
00093 #if 0
00094 /**
00095  * @class ACE_Dev_Poll_Ready_Set
00096  *
00097  * @brief Class that contains the list of "ready" file descriptors.
00098  *
00099  * This class points to an array of pollfd structures corresponding to
00100  * "ready" file descriptors, such as those corresponding to event
00101  * handlers that request an additional callback after being initially
00102  * dispatched (i.e. return a value greater than zero).
00103  * @par
00104  * The idea is to store the "ready" set in an existing area of memory
00105  * that already contains pollfd instances.  Doing so is safe since the
00106  * "ready" set is dispatched before polling for additional events,
00107  * thus avoiding being potentially overwritten during the event poll.
00108  * @par
00109  * When the "ready" set is dispatched, all that needs to be done is to
00110  * iterate over the contents of the array.  There is no need to "walk"
00111  * the array in search of ready file descriptors since the array by
00112  * design only contains ready file descriptors.  As such, this
00113  * implementation of a ready set is much more efficient in the
00114  * presence of a large number of file descriptors in terms of both
00115  * time and space than the one used in the Select_Reactor, for
00116  * example.
00117  */
00118 class ACE_Dev_Poll_Ready_Set
00119 {
00120 public:
00121 
00122   /// Constructor.
00123   ACE_Dev_Poll_Ready_Set (void);
00124 
00125 public:
00126 
00127   /// The array containing the pollfd structures corresponding to the
00128   /// "ready" file descriptors.
00129   struct pollfd *pfds;
00130 
00131   /// The number of "ready" file descriptors in the above array.
00132   int nfds;
00133 
00134 };
00135 #endif  /* 0 */
00136 
00137 // ---------------------------------------------------------------------
00138 
00139 /**
00140  * @class ACE_Dev_Poll_Reactor_Notify
00141  *
00142  * @brief Event handler used for unblocking the ACE_Dev_Poll_Reactor
00143  *        from its event loop.
00144  *
00145  * This event handler is used internally by the ACE_Dev_Poll_Reactor
00146  * as a means to allow a thread other then the one running the event
00147  * loop to unblock the event loop.
00148  */
00149 class ACE_Dev_Poll_Reactor_Notify : public ACE_Reactor_Notify
00150 {
00151 public:
00152 
00153   /// Constructor
00154   ACE_Dev_Poll_Reactor_Notify (void);
00155 
00156   /**
00157    * @name Initialization and Termination Methods
00158    *
00159    * Methods called when initializing and terminating this event
00160    * handler.
00161    */
00162   virtual int open (ACE_Reactor_Impl *,
00163                     ACE_Timer_Queue *timer_queue = 0,
00164                     int disable_notify = 0);
00165   virtual int close (void);
00166 
00167   /**
00168    * Called by a thread when it wants to unblock the Reactor_Impl.
00169    * This wakes up the Reactor_Impl if currently blocked.  Pass over
00170    * both the Event_Handler and the mask to allow the caller to
00171    * dictate which Event_Handler method the Reactor_Impl will
00172    * invoke.  The ACE_Time_Value indicates how long to block
00173    * trying to notify the Reactor_Impl.  If timeout == 0, the
00174    * caller will block until action is possible, else will wait until
00175    * the relative time specified in *timeout elapses).
00176    */
00177   virtual int notify (ACE_Event_Handler *eh = 0,
00178                       ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
00179                       ACE_Time_Value *timeout = 0);
00180 
00181   /// Unimplemented method required by pure virtual method in abstract
00182   /// base class.
00183   /**
00184    * This method's interface is not very compatibile with this
00185    * Reactor's design.  It's not clear why this method is pure virtual
00186    * either.
00187    */
00188   virtual int dispatch_notifications (int &number_of_active_handles,
00189                                       ACE_Handle_Set &rd_mask);
00190 
00191   /// Returns the ACE_HANDLE of the notify pipe on which the reactor
00192   /// is listening for notifications so that other threads can unblock
00193   /// the Reactor_Impl.
00194   virtual ACE_HANDLE notify_handle (void);
00195 
00196   /// Verify whether the buffer has dispatchable info or not.
00197   virtual int is_dispatchable (ACE_Notification_Buffer &buffer);
00198 
00199   /// Handle one notify call represented in @a buffer.  This could be
00200   /// because of a thread trying to unblock the Reactor_Impl.
00201   virtual int dispatch_notify (ACE_Notification_Buffer &buffer);
00202 
00203   /// Read one notify call on the handle into @a buffer.
00204   /// This could be because of a thread trying to unblock the Reactor_Impl.
00205   virtual int read_notify_pipe (ACE_HANDLE handle,
00206                                 ACE_Notification_Buffer &buffer);
00207 
00208   /// Called back by the ACE_Dev_Poll_Reactor when a thread wants to
00209   /// unblock us.
00210   virtual int handle_input (ACE_HANDLE handle);
00211 
00212   /**
00213    * Set the maximum number of times that the handle_input method
00214    * will iterate and dispatch the ACE_Event_Handlers that are
00215    * passed in via the notify queue before breaking out of the event
00216    * loop.  By default, this is set to -1, which means "iterate until
00217    * the queue is empty."  Setting this to a value like "1 or 2" will
00218    * increase "fairness" (and thus prevent starvation) at the expense
00219    * of slightly higher dispatching overhead.
00220    */
00221   virtual void max_notify_iterations (int);
00222 
00223   /**
00224    * Get the maximum number of times that the handle_input method
00225    * will iterate and dispatch the ACE_Event_Handlers that are
00226    * passed in via the notify queue before breaking out of its event
00227    * loop.
00228    */
00229   virtual int max_notify_iterations (void);
00230 
00231   /**
00232    * Purge any notifications pending in this reactor for the specified
00233    * ACE_Event_Handler object. Returns the number of notifications
00234    * purged. Returns -1 on error.
00235    */
00236   virtual int purge_pending_notifications (
00237     ACE_Event_Handler * = 0,
00238     ACE_Reactor_Mask    = ACE_Event_Handler::ALL_EVENTS_MASK);
00239 
00240   /// Dump the state of an object.
00241   virtual void dump (void) const;
00242 
00243 protected:
00244 
00245   /**
00246    * Keep a back pointer to the ACE_Dev_Poll_Reactor.  If this value
00247    * if NULL then the ACE_Dev_Poll_Reactor has been initialized with
00248    * disable_notify_pipe.
00249    */
00250   ACE_Dev_Poll_Reactor *dp_reactor_;
00251 
00252   /**
00253    * Contains the ACE_HANDLE the ACE_Dev_Poll_Reactor is listening
00254    * on, as well as the ACE_HANDLE that threads wanting the attention
00255    * of the ACE_Dev_Poll_Reactor will write to.
00256    */
00257   ACE_Pipe notification_pipe_;
00258 
00259   /**
00260    * Keeps track of the maximum number of times that the
00261    * ACE_Dev_Poll_Reactor_Notify::handle_input method will iterate and
00262    * dispatch the ACE_Event_Handlers that are passed in via the
00263    * notify pipe before breaking out of its recv loop.  By default,
00264    * this is set to -1, which means "iterate until the pipe is empty."
00265    */
00266   int max_notify_iterations_;
00267 
00268 #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
00269   /**
00270    * @brief A user-space queue to store the notifications.
00271    *
00272    * The notification pipe has OS-specific size restrictions.  That
00273    * is, no more than a certain number of bytes may be stored in the
00274    * pipe without blocking.  This limit may be too small for certain
00275    * applications.  In this case, ACE can be configured to store all
00276    * the events in user-space.  The pipe is still needed to wake up
00277    * the reactor thread, but only one event is sent through the pipe
00278    * at a time.
00279    */
00280   ACE_Notification_Queue notification_queue_;
00281 #endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
00282 
00283 };
00284 
00285 // ---------------------------------------------------------------------
00286 
00287 /**
00288  * @class ACE_Dev_Poll_Reactor_Handler_Repository
00289  *
00290  * @internal
00291 
00292  * @brief Used to map ACE_HANDLEs onto the appropriate
00293  *        ACE_Event_Handler *.
00294  *
00295  *
00296  * This class is simply a container that maps a handle to its
00297  * corresponding event handler.  It is not meant for use outside of
00298  * the Dev_Poll_Reactor.
00299  */
00300 class ACE_Dev_Poll_Reactor_Handler_Repository
00301 {
00302 public:
00303 
00304   /// Constructor.
00305   ACE_Dev_Poll_Reactor_Handler_Repository (void);
00306 
00307   /// Initialize a repository of the appropriate @a size.
00308   int open (size_t size);
00309 
00310   /// Close down the repository.
00311   int close (void);
00312 
00313   /**
00314    * @name Repository Manipulation Operations
00315    *
00316    * Methods used to search and modify the handler repository.
00317    */
00318   //@{
00319 
00320   /**
00321    * Return the @c ACE_Event_Handler associated with @c ACE_HANDLE.  If
00322    * @a index_p is non-zero, then return the index location of the
00323    * handle, if found.
00324    */
00325   ACE_Event_Handler *find (ACE_HANDLE handle, size_t *index_p = 0);
00326 
00327   /// Set the event mask for event handler associated with the given
00328   /// handle.
00329   void mask (ACE_HANDLE handle, ACE_Reactor_Mask mask);
00330 
00331   /// Retrieve the event mask for the event handler associated with
00332   /// the given handle.
00333   ACE_Reactor_Mask mask (ACE_HANDLE handle);
00334 
00335   /// Mark the event handler associated with the given handle as
00336   /// "suspended."
00337   void suspend (ACE_HANDLE handle);
00338 
00339   /// Mark the event handler associated with the given handle as
00340   /// "resumed."
00341   void resume (ACE_HANDLE handle);
00342 
00343   /// Is the event handler for the given handle suspended?
00344   int suspended (ACE_HANDLE handle) const;
00345 
00346   /// Bind the ACE_Event_Handler to the @c ACE_HANDLE with the
00347   /// appropriate ACE_Reactor_Mask settings.
00348   int bind (ACE_HANDLE handle,
00349             ACE_Event_Handler *handler,
00350             ACE_Reactor_Mask mask);
00351 
00352   /// Remove the binding for @c ACE_HANDLE; optionally decrement the associated
00353   /// handler's reference count.
00354   int unbind (ACE_HANDLE handle, bool decr_refcnt = true);
00355 
00356   /// Remove all the (@c ACE_HANDLE, @c ACE_Event_Handler) tuples.
00357   int unbind_all (void);
00358 
00359   /**
00360    * @name Sanity Checking
00361    *
00362    * Methods used to prevent "out-of-range" errors when indexing the
00363    * underlying handler array.
00364    */
00365   //@{
00366 
00367   // Check the @a handle to make sure it's a valid @c ACE_HANDLE that
00368   // within the range of legal handles (i.e., greater than or equal to
00369   // zero and less than @c max_size_).
00370   int invalid_handle (ACE_HANDLE handle) const;
00371 
00372   // Check the handle to make sure it's a valid @c ACE_HANDLE that is
00373   // within the range of currently registered handles (i.e., greater
00374   // than or equal to zero and less than @c max_handlep1_).
00375   int handle_in_range (ACE_HANDLE handle) const;
00376 
00377   //@}
00378 
00379   /// Returns the current table size.
00380   size_t size (void) const;
00381 
00382   /// Dump the state of an object.
00383   void dump (void) const;
00384 
00385   /// Declare the dynamic allocation hooks.
00386   ACE_ALLOC_HOOK_DECLARE;
00387 
00388 private:
00389 
00390   /// Maximum number of handles.
00391   int max_size_;
00392 
00393   /// The underlying array of event handlers.
00394   /**
00395    * The array of event handlers is directly indexed directly using
00396    * an @c ACE_HANDLE value.  This is Unix-specific.
00397    */
00398   ACE_Dev_Poll_Event_Tuple *handlers_;
00399 
00400 };
00401 
00402 // ---------------------------------------------------------------------
00403 
00404 /**
00405  * @class ACE_Dev_Poll_Reactor
00406  *
00407  * @brief A `/dev/poll' or `/dev/epoll' based Reactor implemenatation.
00408  *
00409  * @attention The Linux epoll implementation works quite well and is
00410  * fully supported; however, the /dev/poll implementation is @em experimental.
00411  *
00412  * The ACE_Dev_Poll_Reactor uses the `/dev/poll' or '/dev/epoll'
00413  * character devices to demultiplex events on a given set of file
00414  * descriptors.  Unlike @c select(), `/dev/poll' and `/dev/epoll' have
00415  * no hard-coded limit on the number of file descriptors that may be
00416  * handled at any given time.  As such, the ACE_Dev_Poll_Reactor can
00417  * generally handle a much larger number of file descriptors than
00418  * @c select() -based reactors.  Furthermore, since `/dev/poll' and
00419  * `/dev/epoll' both return a set of file descriptors that are active,
00420  * there is no need to "walk" the set of file descriptors to determine
00421  * which ones are active, such as what is done with the @c select() and
00422  * @c poll() system calls.  All returned file descriptors are active.
00423  * This makes event dispatching very efficient.
00424  *
00425  * @note In general, this reactor may only be used to demultiplex
00426  *       events on sockets.  Demultiplexing events on pipes, for
00427  *       example may not work.  This is due to a limitation in the
00428  *       underlying `/dev/poll' device driver.
00429  *
00430  * @note It is only possible to achieve millisecond timeout
00431  *       resolutions with the @c ACE_Dev_Poll_Reactor.  However, the
00432  *       timeout resolution for timers is independent of the reactors
00433  *       timeout resolution.  As such, it may be possible to achieve
00434  *       sub-millisecond timeout resolutions for timers but that is
00435  *       entirely platform dependent.
00436  */
00437 
00438 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00439 typedef ACE_Token ACE_DEV_POLL_TOKEN;
00440 #else
00441 typedef ACE_Noop_Token ACE_DEV_POLL_TOKEN;
00442 #endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
00443 typedef ACE_Reactor_Token_T<ACE_DEV_POLL_TOKEN> ACE_Dev_Poll_Reactor_Token;
00444 
00445 class ACE_Export ACE_Dev_Poll_Reactor : public ACE_Reactor_Impl
00446 {
00447 public:
00448 
00449   /// Initialize @c ACE_Dev_Poll_Reactor with the default size.
00450   /**
00451    * The default size for the @c ACE_Dev_Poll_Reactor is the maximum
00452    * number of open file descriptors for the process.
00453    */
00454   ACE_Dev_Poll_Reactor (ACE_Sig_Handler * = 0,
00455                         ACE_Timer_Queue * = 0,
00456                         int disable_notify_pipe = 0,
00457                         ACE_Reactor_Notify *notify = 0,
00458                         int mask_signals = 1,
00459                         int s_queue = ACE_DEV_POLL_TOKEN::FIFO);
00460 
00461   /// Initialize ACE_Dev_Poll_Reactor with size @a size.
00462   /**
00463    * @note On Unix platforms, the @a size parameter should be as large
00464    *       as the maximum number of file descriptors allowed for a
00465    *       given process.  This is necessary since a file descriptor
00466    *       is used to directly index the array of event handlers
00467    *       maintained by the Reactor's handler repository.  Direct
00468    *       indexing is used for efficiency reasons.  If the size
00469    *       parameter is less than the process maximum, the process
00470    *       maximum will be decreased in order to prevent potential
00471    *       access violations.
00472    */
00473   ACE_Dev_Poll_Reactor (size_t size,
00474                         int restart = 0,
00475                         ACE_Sig_Handler * = 0,
00476                         ACE_Timer_Queue * = 0,
00477                         int disable_notify_pipe = 0,
00478                         ACE_Reactor_Notify *notify = 0,
00479                         int mask_signals = 1,
00480                         int s_queue = ACE_DEV_POLL_TOKEN::FIFO);
00481 
00482   /// Close down and release all resources.
00483   virtual ~ACE_Dev_Poll_Reactor (void);
00484 
00485   /// Initialization.
00486   virtual int open (size_t size,
00487                     int restart = 0,
00488                     ACE_Sig_Handler * = 0,
00489                     ACE_Timer_Queue * = 0,
00490                     int disable_notify_pipe = 0,
00491                     ACE_Reactor_Notify * = 0);
00492 
00493   /**
00494    * @param handle allows the reactor to check if the caller is
00495    *        valid.
00496    *
00497    * @return 0 if the size of the current message has been put in
00498    *         size.  -1 if not.
00499    */
00500   virtual int current_info (ACE_HANDLE handle, size_t & /* size */);
00501 
00502   /// Use a user specified signal handler instead.
00503   virtual int set_sig_handler (ACE_Sig_Handler *signal_handler);
00504 
00505   /// Set a user-specified timer queue.
00506   virtual int timer_queue (ACE_Timer_Queue *tq);
00507 
00508   /// Get the timer queue
00509   /// @return The current @c ACE_Timer_Queue.
00510   virtual ACE_Timer_Queue *timer_queue (void) const;
00511 
00512   /// Close down and release all resources.
00513   virtual int close (void);
00514 
00515   // = Event loop drivers.
00516   /**
00517    * Returns non-zero if there are I/O events "ready" for dispatching,
00518    * but does not actually dispatch the event handlers.  By default,
00519    * don't block while checking this, i.e., "poll".
00520    *
00521    * @note It is only possible to achieve millisecond timeout
00522    *       resolutions with the @c ACE_Dev_Poll_Reactor.
00523    */
00524   virtual int work_pending (
00525     const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero);
00526 
00527   /**
00528    * This event loop driver blocks for up to @a max_wait_time before
00529    * returning.  It will return earlier if events occur.  Note that
00530    * @a max_wait_time can be 0, in which case this method blocks
00531    * indefinitely until events occur.
00532    * @par
00533    * @a max_wait_time is decremented to reflect how much time this
00534    * call took.  For instance, if a time value of 3 seconds is passed
00535    * to @c handle_events() and an event occurs after 2 seconds,
00536    * @a max_wait_time will equal 1 second.  This can be used if an
00537    * application wishes to handle events for some fixed amount of
00538    * time.
00539    * @par
00540    * The only difference between @c alertable_handle_events() and
00541    * handle_events() is that in the alertable case, the event loop
00542    * will return when the system queues an I/O completion routine or
00543    * an Asynchronous Procedure Call.
00544    *
00545    * @return  The total number of @c ACE_Event_Handlers that were
00546    *          dispatched, 0 if the @a max_wait_time elapsed without
00547    *          dispatching any handlers, or -1 if an error occurs.
00548 
00549    * @note It is only possible to achieve millisecond timeout
00550    *       resolutions with the @c ACE_Dev_Poll_Reactor.
00551    */
00552   virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
00553   virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0);
00554 
00555   /**
00556    * This method is just like the one above, except the
00557    * @a max_wait_time value is a reference and can therefore never be
00558    * @c NULL.
00559    *
00560    * @note It is only possible to achieve millisecond timeout
00561    *       resolutions with the @c ACE_Dev_Poll_Reactor.
00562    */
00563   virtual int handle_events (ACE_Time_Value &max_wait_time);
00564   virtual int alertable_handle_events (ACE_Time_Value &max_wait_time);
00565 
00566   // = Event handling control.
00567 
00568   /**
00569    * @return The status of Reactor.  If this function returns 0, the
00570    *         reactor is actively handling events.  If it returns
00571    *         non-zero, @c handle_events() and
00572    *         @c handle_alertable_events() return -1 immediately.
00573    */
00574   virtual int deactivated (void);
00575 
00576   /**
00577    * Control whether the Reactor will handle any more incoming events
00578    * or not.  If @a do_stop == 1, the Reactor will be disabled.  By
00579    * default, a reactor is in active state and can be
00580    * deactivated/reactived as desired.
00581    */
00582   virtual void deactivate (int do_stop);
00583 
00584   // = Register and remove Handlers.
00585 
00586   /// Register @a event_handler with @a mask.  The I/O handle will
00587   /// always come from get_handle on the event_handler.
00588   virtual int register_handler (ACE_Event_Handler *event_handler,
00589                                 ACE_Reactor_Mask mask);
00590 
00591   /// Register @a event_handler with @a mask.  The I/O handle is
00592   /// provided through the @a io_handle parameter.
00593   virtual int register_handler (ACE_HANDLE io_handle,
00594                                 ACE_Event_Handler *event_handler,
00595                                 ACE_Reactor_Mask mask);
00596 
00597   /**
00598    * Register an @a event_handler that will be notified when
00599    * @a event_handle is signaled.  @a mask specifies the network
00600    * events that the @a event_handler is interested in.
00601    */
00602   virtual int register_handler (ACE_HANDLE event_handle,
00603                                 ACE_HANDLE io_handle,
00604                                 ACE_Event_Handler *event_handler,
00605                                 ACE_Reactor_Mask mask);
00606 
00607   /// Register @a event_handler> with all the @a handles> in the @c
00608   /// Handle_Set.
00609   virtual int register_handler (const ACE_Handle_Set &handles,
00610                                 ACE_Event_Handler *event_handler,
00611                                 ACE_Reactor_Mask mask);
00612 
00613   /**
00614    * Register @a new_sh to handle the signal @a signum using the
00615    * @a new_disp.  Returns the @a old_sh that was previously
00616    * registered (if any), along with the @a old_disp of the signal
00617    * handler.
00618    */
00619   virtual int register_handler (int signum,
00620                                 ACE_Event_Handler *new_sh,
00621                                 ACE_Sig_Action *new_disp = 0,
00622                                 ACE_Event_Handler **old_sh = 0,
00623                                 ACE_Sig_Action *old_disp = 0);
00624 
00625   /// Registers <new_sh> to handle a set of signals <sigset> using the
00626   /// <new_disp>.
00627   virtual int register_handler (const ACE_Sig_Set &sigset,
00628                                 ACE_Event_Handler *new_sh,
00629                                 ACE_Sig_Action *new_disp = 0);
00630 
00631   /// Removes @a event_handler.
00632   /**
00633    * @note The I/O handle will be obtained using @c get_handle()
00634    *       method of @a event_handler .  If @a mask ==
00635    *       @c ACE_Event_Handler::DONT_CALL then the @c handle_close()
00636    *       method of the @a event_handler is not invoked.
00637    */
00638   virtual int remove_handler (ACE_Event_Handler *event_handler,
00639                               ACE_Reactor_Mask mask);
00640 
00641   /**
00642    * Removes @a handle.  If @a mask == ACE_Event_Handler::DONT_CALL
00643    * then the <handle_close> method of the associated <event_handler>
00644    * is not invoked.
00645    */
00646   virtual int remove_handler (ACE_HANDLE handle,
00647                               ACE_Reactor_Mask mask);
00648 
00649   /**
00650    * Removes all handles in <handle_set>.  If @a mask ==
00651    * ACE_Event_Handler::DONT_CALL then the <handle_close> method of
00652    * the associated <event_handler>s is not invoked.
00653    */
00654   virtual int remove_handler (const ACE_Handle_Set &handle_set,
00655                               ACE_Reactor_Mask mask);
00656 
00657   /**
00658    * Remove the ACE_Event_Handler currently associated with @a signum.
00659    * Install the new disposition (if given) and return the previous
00660    * disposition (if desired by the caller).  Returns 0 on success and
00661    * -1 if @a signum is invalid.
00662    */
00663   virtual int remove_handler (int signum,
00664                               ACE_Sig_Action *new_disp,
00665                               ACE_Sig_Action *old_disp = 0,
00666                               int sigkey = -1);
00667 
00668   /// Calls <remove_handler> for every signal in <sigset>.
00669   virtual int remove_handler (const ACE_Sig_Set &sigset);
00670 
00671   // = Suspend and resume Handlers.
00672 
00673   /// Suspend event_handler temporarily.  Use
00674   /// ACE_Event_Handler::get_handle() to get the handle.
00675   virtual int suspend_handler (ACE_Event_Handler *event_handler);
00676 
00677   /// Suspend handle temporarily.
00678   virtual int suspend_handler (ACE_HANDLE handle);
00679 
00680   /// Suspend all handles in handle set temporarily.
00681   virtual int suspend_handler (const ACE_Handle_Set &handles);
00682 
00683   /// Suspend all handles temporarily.
00684   virtual int suspend_handlers (void);
00685 
00686   /// Resume event_handler. Use ACE_Event_Handler::get_handle() to
00687   /// get the handle.
00688   virtual int resume_handler (ACE_Event_Handler *event_handler);
00689 
00690   /// Resume handle.
00691   virtual int resume_handler (ACE_HANDLE handle);
00692 
00693   /// Resume all handles in handle set.
00694   virtual int resume_handler (const ACE_Handle_Set &handles);
00695 
00696   /// Resume all handles.
00697   virtual int resume_handlers (void);
00698 
00699   /// Does the reactor allow the application to resume the handle on
00700   /// its own, i.e., can it pass on the control of handle resumption to
00701   /// the application.
00702   virtual int resumable_handler (void);
00703 
00704   /// Return 1 if we any event associations were made by the reactor
00705   /// for the handles that it waits on, 0 otherwise.
00706   virtual int uses_event_associations (void);
00707 
00708   // = Timer management.
00709 
00710   /**
00711    * Schedule an ACE_Event_Handler that will expire after an amount
00712    * of time.  The return value of this method, a timer_id value,
00713    * uniquely identifies the event_handler in the ACE_Reactor's
00714    * internal list of timers.
00715    * This timer_id value can be used to cancel the timer
00716    * with the cancel_timer() call.
00717    *
00718    * @see cancel_timer()
00719    * @see reset_timer_interval()
00720    *
00721    * @param event_handler  event handler to schedule on reactor
00722    * @param arg   argument passed to the handle_timeout() method of
00723    *              event_handler.
00724    * @param delay  time interval after which the timer will expire.
00725    * @param interval  time interval for which the timer will be
00726    *                  automatically rescheduled.
00727    * @return -1 on failure, a timer_id value on success
00728    */
00729   virtual long schedule_timer (ACE_Event_Handler *event_handler,
00730                                const void *arg,
00731                                const ACE_Time_Value &delay,
00732                                const ACE_Time_Value &interval = ACE_Time_Value::zero);
00733 
00734   /**
00735    * Resets the interval of the timer represented by @a timer_id to
00736    * @a interval, which is specified in relative time to the current
00737    * <gettimeofday>.  If @a interval is equal to
00738    * ACE_Time_Value::zero, the timer will become a non-rescheduling
00739    * timer.  Returns 0 if successful, -1 if not.
00740    */
00741   virtual int reset_timer_interval (long timer_id,
00742                                     const ACE_Time_Value &interval);
00743 
00744   /// Cancel all Event_Handlers that match the address of
00745   /// @a event_handler.  Returns number of handlers cancelled.
00746   virtual int cancel_timer (ACE_Event_Handler *event_handler,
00747                             int dont_call_handle_close = 1);
00748 
00749   /**
00750    * Cancel the single event handler that matches the @a timer_id value
00751    * (which was returned from the schedule method).  If @a arg is
00752    * non-NULL then it will be set to point to the ``magic cookie''
00753    * argument passed in when the event handler was registered.  This
00754    * makes it possible to free up the memory and avoid memory leaks.
00755    * Returns 1 if cancellation succeeded and 0 if the @a timer_id
00756    * wasn't found.
00757    */
00758   virtual int cancel_timer (long timer_id,
00759                             const void **arg = 0,
00760                             int dont_call_handle_close = 1);
00761 
00762   // = High-level event handler scheduling operations
00763 
00764   /// Add @a masks_to_be_added to the @a event_handler's entry.
00765   /// @a event_handler must already have been registered.
00766   virtual int schedule_wakeup (ACE_Event_Handler *event_handler,
00767                                ACE_Reactor_Mask masks_to_be_added);
00768 
00769   /// Add @a masks_to_be_added to the @a handle's entry.  <event_handler>
00770   /// associated with @a handle must already have been registered.
00771   virtual int schedule_wakeup (ACE_HANDLE handle,
00772                                ACE_Reactor_Mask masks_to_be_added);
00773 
00774   /// Clear @a masks_to_be_cleared from the @a event_handler's entry.
00775   virtual int cancel_wakeup (ACE_Event_Handler *event_handler,
00776                              ACE_Reactor_Mask masks_to_be_cleared);
00777 
00778   /// Clear @a masks_to_be_cleared from the @a handle's entry.
00779   virtual int cancel_wakeup (ACE_HANDLE handle,
00780                              ACE_Reactor_Mask masks_to_be_cleared);
00781 
00782   // = Notification methods.
00783 
00784   /**
00785    * Notify @a event_handler of @a mask event.  The ACE_Time_Value
00786    * indicates how long to blocking trying to notify.  If @a timeout ==
00787    * 0, the caller will block until action is possible, else will wait
00788    * until the relative time specified in @a timeout elapses).
00789    */
00790   virtual int notify (ACE_Event_Handler *event_handler = 0,
00791                       ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,
00792                       ACE_Time_Value * = 0);
00793 
00794   /**
00795    * Set the maximum number of times that ACE_Reactor_Impl will
00796    * iterate and dispatch the <ACE_Event_Handlers> that are passed in
00797    * via the notify queue before breaking out of its
00798    * <ACE_Message_Queue::dequeue> loop.  By default, this is set to
00799    * -1, which means "iterate until the queue is empty."  Setting this
00800    * to a value like "1 or 2" will increase "fairness" (and thus
00801    * prevent starvation) at the expense of slightly higher dispatching
00802    * overhead.
00803    */
00804   virtual void max_notify_iterations (int);
00805 
00806   /**
00807    * Get the maximum number of times that the ACE_Reactor_Impl will
00808    * iterate and dispatch the <ACE_Event_Handlers> that are passed in
00809    * via the notify queue before breaking out of its
00810    * <ACE_Message_Queue::dequeue> loop.
00811    */
00812   virtual int max_notify_iterations (void);
00813 
00814   /**
00815    * Purge any notifications pending in this reactor for the specified
00816    * ACE_Event_Handler object. Returns the number of notifications
00817    * purged. Returns -1 on error.
00818    */
00819   virtual int purge_pending_notifications (ACE_Event_Handler * = 0,
00820                                            ACE_Reactor_Mask    = ACE_Event_Handler::ALL_EVENTS_MASK);
00821 
00822   /**
00823    * Return the Event_Handler associated with @a handle.  Return 0 if
00824    * @a handle is not registered.
00825    */
00826   virtual ACE_Event_Handler *find_handler (ACE_HANDLE handle);
00827 
00828   /**
00829    * Check to see if @a handle is associated with a valid Event_Handler
00830    * bound to @a mask.  Return the @a event_handler associated with this
00831    * @c handler if @a event_handler != 0.
00832    */
00833   virtual int handler (ACE_HANDLE handle,
00834                        ACE_Reactor_Mask mask,
00835                        ACE_Event_Handler **event_handler = 0);
00836 
00837   /**
00838    * Check to see if @a signum is associated with a valid Event_Handler
00839    * bound to a signal.  Return the @a event_handler associated with
00840    * this @c handler if @a event_handler != 0.
00841    */
00842   virtual int handler (int signum,
00843                        ACE_Event_Handler ** = 0);
00844 
00845   /// Returns true if Reactor has been successfully initialized, else
00846   /// false.
00847   virtual bool initialized (void);
00848 
00849   /// Returns the current size of the Reactor's internal descriptor
00850   /// table.
00851   virtual size_t size (void) const;
00852 
00853   /// Returns a reference to the Reactor's internal lock.
00854   virtual ACE_Lock &lock (void);
00855 
00856   /// Wake up all threads waiting in the event loop.
00857   virtual void wakeup_all_threads (void);
00858 
00859   /// Transfers ownership of Reactor_Impl to the new_owner.
00860   /**
00861    * @note There is no need to set the owner of the event loop for the
00862    *       ACE_Dev_Poll_Reactor.  Multiple threads may invoke the
00863    *       event loop simulataneously.  As such, this method is a
00864    *       no-op.
00865    */
00866   virtual int owner (ACE_thread_t new_owner, ACE_thread_t *old_owner = 0);
00867 
00868   /// Return the ID of the "owner" thread.
00869   /**
00870    * @note There is no need to set the owner of the event loop for the
00871    *       ACE_Dev_Poll_Reactor.  Multiple threads may invoke the
00872    *       event loop simulataneously.  As such, this method is a
00873    *       no-op.
00874    */
00875   virtual int owner (ACE_thread_t *owner);
00876 
00877   /// Get the existing restart value.
00878   virtual int restart (void);
00879 
00880   /// Set a new value for restart and return the original value.
00881   /**
00882    * @param r If zero, then the event loop will not be automatically
00883    *          restarted if the underlying poll is interrupted via the
00884    *          INTR (interrupt) signal.
00885    *
00886    * @return Returns the previous "restart" value.
00887    */
00888   virtual int restart (int r);
00889 
00890   /// Set position of the owner thread.
00891   /**
00892    * @note This is currently a no-op.
00893    */
00894   virtual void requeue_position (int);
00895 
00896   /// Get position of the owner thread.
00897   /**
00898    * @note This is currently a no-op.
00899    */
00900   virtual int requeue_position (void);
00901 
00902   /**
00903    * @name Low-level wait_set mask manipulation methods
00904    *
00905    * Low-level methods to manipulate the event/reactor mask associated
00906    * with a handle and event handler when polling for events.
00907    * @par
00908    * The "interest set," i.e. the wait set, can be directly
00909    * manipulated with these methods.
00910    */
00911   //@{
00912 
00913   /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the
00914   /// event_handler and mask.
00915   /**
00916    * @return Old mask on success, -1 on error.
00917    */
00918   virtual int mask_ops (ACE_Event_Handler *event_handler,
00919                         ACE_Reactor_Mask mask,
00920                         int ops);
00921 
00922   /// GET/SET/ADD/CLR the dispatch MASK "bit" bound with the handle
00923   /// and mask.
00924   /**
00925    * @return Old mask on success, -1 on error.
00926    */
00927   virtual int mask_ops (ACE_HANDLE handle,
00928                         ACE_Reactor_Mask mask,
00929                         int ops);
00930 
00931   //@}
00932 
00933   /**
00934    * @name Low-level ready_set mask manipulation methods
00935    *
00936    * These methods are unimplemented.
00937    */
00938   //@{
00939 
00940   /// GET/SET/ADD/CLR the ready "bit" bound with the event_handler
00941   /// and mask.
00942   virtual int ready_ops (ACE_Event_Handler *event_handler,
00943                          ACE_Reactor_Mask mask,
00944                          int ops);
00945 
00946   /// GET/SET/ADD/CLR the ready "bit" bound with the handle and mask.
00947   virtual int ready_ops (ACE_HANDLE handle,
00948                          ACE_Reactor_Mask,
00949                          int ops);
00950 
00951   //@}
00952 
00953   /// Dump the state of an object.
00954   virtual void dump (void) const;
00955 
00956   /// Declare the dynamic allocation hooks.
00957   ACE_ALLOC_HOOK_DECLARE;
00958 
00959 protected:
00960 
00961   class Token_Guard;
00962 
00963   /// Non-locking version of wait_pending().
00964   /**
00965    * Returns non-zero if there are I/O events "ready" for dispatching,
00966    * but does not actually dispatch the event handlers.  By default,
00967    * don't block while checking this, i.e., "poll".
00968    *
00969    * @note It is only possible to achieve millisecond timeout
00970    *       resolutions with the ACE_Dev_Poll_Reactor.
00971    */
00972   int work_pending_i (ACE_Time_Value *max_wait_time);
00973 
00974   /// Poll for events and return the number of event handlers that
00975   /// were dispatched.
00976   /**
00977    * This is a helper method called by all handle_events() methods.
00978    */
00979   int handle_events_i (ACE_Time_Value *max_wait_time, Token_Guard &guard);
00980 
00981   /// Perform the upcall with the given event handler method.
00982   int upcall (ACE_Event_Handler *event_handler,
00983               int (ACE_Event_Handler::*callback)(ACE_HANDLE),
00984               ACE_HANDLE handle);
00985 
00986   /**
00987    * Dispatch ACE_Event_Handlers for time events, I/O events, and
00988    * signal events.  Returns the total number of ACE_Event_Handlers
00989    * that were dispatched or -1 if something goes wrong.
00990    */
00991   int dispatch (Token_Guard &guard);
00992 
00993   /// Dispatch a single timer, if ready.
00994   /// Returns: 0 if no timers ready (token still held),
00995   ///          1 if a timer was expired (token released),
00996   ///         -1 on error (token still held).
00997   int dispatch_timer_handler (Token_Guard &guard);
00998 
00999   /// Dispatch an IO event to the corresponding event handler. Returns
01000   /// Returns: 0 if no events ready (token still held),
01001   ///          1 if an event was expired (token released),
01002   ///         -1 on error (token still held).
01003   int dispatch_io_event (Token_Guard &guard);
01004 
01005   /// Register the given event handler with the reactor.
01006   int register_handler_i (ACE_HANDLE handle,
01007                           ACE_Event_Handler *eh,
01008                           ACE_Reactor_Mask mask);
01009 
01010   /// Remove the event handler associated with the given handle and
01011   /// event mask from the "interest set."
01012   int remove_handler_i (ACE_HANDLE handle, ACE_Reactor_Mask mask);
01013 
01014   /// Temporarily remove the given handle from the "interest set."
01015   int suspend_handler_i (ACE_HANDLE handle);
01016 
01017   /// Place the given handle that was temporarily removed from the
01018   /// "interest set," i.e that was suspended, back in to the interest
01019   /// set.  The given handle will once again be polled for events.
01020   int resume_handler_i (ACE_HANDLE handle);
01021 
01022   /// GET/SET/ADD/CLR the dispatch MASK "bit" bound with the handle
01023   /// and mask.  This internal helper method acquires no lock.
01024   /**
01025    * @return Old mask on success, -1 on error.
01026    */
01027   int mask_ops_i (ACE_HANDLE handle,
01028                   ACE_Reactor_Mask mask,
01029                   int ops);
01030 
01031   /// Convert a reactor mask to its corresponding poll() event mask.
01032   short reactor_mask_to_poll_event (ACE_Reactor_Mask mask);
01033 
01034 protected:
01035 
01036   /// Has the reactor been initialized.
01037   bool initialized_;
01038 
01039   /// The file descriptor associated with the open `/dev/poll' or
01040   /// `/dev/epoll' device.
01041   /**
01042    * All interactions with the `/dev/poll' or `/dev/epoll' device are
01043    * done through this file descriptor.
01044    */
01045   ACE_HANDLE poll_fd_;
01046 
01047   /// The maximum number of file descriptors over which demultiplexing
01048   /// will occur.
01049   size_t size_;
01050 
01051   /// Track HANDLES we are interested in for various events that must
01052   /// be dispatched *without* polling.
01053   /// ACE_Dev_Poll_Ready_Set ready_set_;
01054 
01055 #if defined (ACE_HAS_EVENT_POLL)
01056   /// Table of event structures to be filled by epoll_wait:
01057   struct epoll_event *events_;
01058 
01059   /// Pointer to the next epoll_event array element that contains the next
01060   /// event to be dispatched.
01061   struct epoll_event *start_pevents_;
01062 
01063   /// The last element in the event array plus one.
01064   /**
01065    * The loop that dispatches IO events stops when this->start_pevents_ ==
01066    * this->end_pevents_.
01067    */
01068   struct epoll_event *end_pevents_;
01069 
01070 #else
01071   /// The pollfd array that `/dev/poll' will feed its results to.
01072   struct pollfd *dp_fds_;
01073 
01074 
01075   /// Pointer to the next pollfd array element that contains the next
01076   /// event to be dispatched.
01077   struct pollfd *start_pfds_;
01078 
01079   /// The last element in the pollfd array plus one.
01080   /**
01081    * The loop that dispatches IO events stops when this->start_pfds ==
01082    * this->end_pfds_.
01083    */
01084   struct pollfd *end_pfds_;
01085 #endif  /* ACE_HAS_EVENT_POLL */
01086 
01087   /// This flag is used to keep track of whether we are actively handling
01088   /// events or not.
01089   sig_atomic_t deactivated_;
01090 
01091   /// Lock used for synchronization of reactor state.
01092   ACE_Dev_Poll_Reactor_Token token_;
01093 
01094   /// Adapter used to return internal lock to outside world.
01095   ACE_Lock_Adapter<ACE_Dev_Poll_Reactor_Token> lock_adapter_;
01096 
01097   /// The repository that contains all registered event handlers.
01098   ACE_Dev_Poll_Reactor_Handler_Repository handler_rep_;
01099 
01100   /// Defined as a pointer to allow overriding by derived classes...
01101   ACE_Timer_Queue *timer_queue_;
01102 
01103   /// Keeps track of whether we should delete the timer queue (if we
01104   /// didn't create it, then we don't delete it).
01105   bool delete_timer_queue_;
01106 
01107   /// Handle signals without requiring global/static variables.
01108   ACE_Sig_Handler *signal_handler_;
01109 
01110   /// Keeps track of whether we should delete the signal handler (if we
01111   /// didn't create it, then we don't delete it).
01112   bool delete_signal_handler_;
01113 
01114   /// Callback object that unblocks the <ACE_Select_Reactor> if it's
01115   /// sleeping.
01116   ACE_Reactor_Notify *notify_handler_;
01117 
01118   /// Keeps track of whether we need to delete the notify handler (if
01119   /// we didn't create it, then we don't delete it).
01120   bool delete_notify_handler_;
01121 
01122   /// Flag that determines if signals are masked during event
01123   /// dispatching.
01124   /**
01125    * If 0 then the Reactor will not mask the signals during the event
01126    * dispatching.  This is useful for applications that do not
01127    * register any signal handlers and want to reduce the overhead
01128    * introduce by the kernel level locks required to change the mask.
01129    */
01130   int mask_signals_;
01131 
01132   /// Restart the handle_events event loop method automatically when
01133   /// polling function in use (ioctl() in this case) is interrupted
01134   /// via an EINTR signal.
01135   int restart_;
01136 
01137 protected:
01138 
01139   /**
01140    * @class Token_Guard
01141    *
01142    * @brief A helper class that helps grabbing, releasing and waiting
01143    * on tokens for a thread that needs access to the reactor's token.
01144    */
01145   class ACE_Export Token_Guard
01146   {
01147   public:
01148 
01149     /// Constructor that will grab the token for us
01150     Token_Guard (ACE_Dev_Poll_Reactor_Token &token);
01151 
01152     /// Destructor. This will release the token if it hasn't been
01153     /// released till this point
01154     ~Token_Guard (void);
01155 
01156     /// Release the token ..
01157     void release_token (void);
01158 
01159     /// Returns whether the thread that created this object owns the
01160     /// token or not.
01161     int is_owner (void);
01162 
01163     /// A helper method that acquires the token 1) at a low priority, and
01164     /// 2) wait quietly for the token, not waking another thread. This
01165     /// is appropriate for cases where a thread wants to wait for and
01166     /// dispatch an event, not causing an existing waiter to relinquish the
01167     /// token, and also queueing up behind other threads waiting to modify
01168     /// event records.
01169     int acquire_quietly (ACE_Time_Value *max_wait = 0);
01170 
01171     /// A helper method that acquires the token at a high priority, and
01172     /// does wake the current token holder.
01173     int acquire (ACE_Time_Value *max_wait = 0);
01174 
01175   private:
01176 
01177     Token_Guard (void);
01178 
01179   private:
01180 
01181     /// The Reactor token.
01182     ACE_Dev_Poll_Reactor_Token &token_;
01183 
01184     /// Flag that indicate whether the thread that created this object
01185     /// owns the token or not. A value of 0 indicates that this class
01186     /// hasn't got the token (and hence the thread) and a value of 1
01187     /// vice-versa.
01188     int owner_;
01189 
01190   };
01191 
01192 };
01193 
01194 
01195 /**
01196  * @class ACE_Dev_Poll_Handler_Guard
01197  *
01198  * @brief Class used to make event handler reference count
01199  *        manipulation exception-safe.
01200  *
01201  * This class makes the reference count manipulation that occurs
01202  * during an upcall exception-safe.  Prior to dispatching the event
01203  * handler, the reference count is increased.  Once the upcall for the
01204  * given event handler is complete, its reference count will be decreased.
01205  */
01206 class ACE_Dev_Poll_Handler_Guard
01207 {
01208 public:
01209 
01210   /// Constructor
01211   /**
01212    * The constructor checks to see if @a eh is a reference-counted handler and
01213    * remember that for later. If @a eh is reference counted, its reference
01214    * count is incremented unless @a do_incr is false.
01215    * @a do_incr should be false if the reference count was incremented
01216    * independently of this guard, for example, on a notify handler since
01217    * the reference count is incremented when the notify is queued.
01218    */
01219   ACE_Dev_Poll_Handler_Guard (ACE_Event_Handler *eh, bool do_incr = true);
01220 
01221   /// Destructor
01222   /**
01223    * The destructor decrements the reference count on the event
01224    * handler corresponding to the given handle.
01225    */
01226   ~ACE_Dev_Poll_Handler_Guard (void);
01227 
01228   /// Release the event handler from this guard; when the destructor is
01229   /// called, the handler's reference count will not be decremented.
01230   void release (void);
01231 
01232 private:
01233 
01234   /// The event handler being managed.
01235   ACE_Event_Handler *eh_;
01236 
01237   /// true if eh_ is a reference-counted handler.
01238   bool refcounted_;
01239 
01240 };
01241 
01242 ACE_END_VERSIONED_NAMESPACE_DECL
01243 
01244 #if defined (__ACE_INLINE__)
01245 # include "ace/Dev_Poll_Reactor.inl"
01246 #endif /* __ACE_INLINE__ */
01247 
01248 #endif  /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */
01249 
01250 #include /**/ "ace/post.h"
01251 
01252 #endif  /* ACE_DEV_POLL_REACTOR_H */

Generated on Tue Feb 2 17:18:39 2010 for ACE by  doxygen 1.4.7