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