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

Generated on Sun Jan 27 12:05:24 2008 for ACE by doxygen 1.3.6