Dev_Poll_Reactor.h

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

Generated on Thu Nov 9 09:41:50 2006 for ACE by doxygen 1.3.6