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 */