3 //=============================================================================
5 * @file Select_Reactor_Base.h
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 //=============================================================================
11 #ifndef ACE_SELECT_REACTOR_BASE_H
12 #define ACE_SELECT_REACTOR_BASE_H
14 #include /**/ "ace/pre.h"
16 #include "ace/Timer_Queuefwd.h"
18 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 #endif /* ACE_LACKS_PRAGMA_ONCE */
22 #include "ace/Event_Handler.h"
23 #include "ace/Handle_Set.h"
25 #include "ace/Reactor_Impl.h"
27 #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
28 # include "ace/Notification_Queue.h"
29 #endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
31 #if defined (ACE_WIN32) || defined (ACE_MQX)
32 # ifndef ACE_SELECT_REACTOR_BASE_USES_HASH_MAP
33 # define ACE_SELECT_REACTOR_BASE_USES_HASH_MAP
37 #ifdef ACE_SELECT_REACTOR_BASE_USES_HASH_MAP
38 # include "ace/Null_Mutex.h"
39 # include "ace/Hash_Map_Manager_T.h"
40 # include "ace/Functor.h" /* For ACE_Hash<void *> */
41 # include <functional> /* For std::equal_to<> */
43 # include "ace/Array_Base.h"
44 #endif /* ACE_SELECT_REACTOR_BASE_USES_HASH_MAP */
46 #if !defined (ACE_DISABLE_NOTIFY_PIPE_DEFAULT)
47 # define ACE_DISABLE_NOTIFY_PIPE_DEFAULT 0
48 #endif /* ACE_DISABLE_NOTIFY_PIPE_DEFAULT */
50 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
52 // Add useful typedefs to simplify the following code.
53 typedef void (ACE_Handle_Set::*ACE_FDS_PTMF
) (ACE_HANDLE
);
54 typedef int (ACE_Event_Handler::*ACE_EH_PTMF
) (ACE_HANDLE
);
56 // Forward declaration.
57 class ACE_Select_Reactor_Impl
;
58 class ACE_Sig_Handler
;
61 * @class ACE_Select_Reactor_Handle_Set
63 * @brief Track handles we are interested for various events.
65 class ACE_Export ACE_Select_Reactor_Handle_Set
68 /// Read events (e.g., input pending, accept pending).
69 ACE_Handle_Set rd_mask_
;
71 /// Write events (e.g., flow control abated, non-blocking connection
73 ACE_Handle_Set wr_mask_
;
75 /// Exception events (e.g., SIG_URG).
76 ACE_Handle_Set ex_mask_
;
80 * @class ACE_Event_Tuple
82 * @brief An ACE_Event_Handler and its associated ACE_HANDLE.
84 * One ACE_Event_Handler is registered for one or more
85 * ACE_HANDLE. At various points, this information must be
86 * stored explicitly. This class provides a lightweight
92 /// Default constructor.
93 ACE_Event_Tuple (void);
96 ACE_Event_Tuple (ACE_Event_Handler
*eh
, ACE_HANDLE h
);
98 /// Equality operator.
99 bool operator== (const ACE_Event_Tuple
&rhs
) const;
101 /// Inequality operator.
102 bool operator!= (const ACE_Event_Tuple
&rhs
) const;
108 /// ACE_Event_Handler associated with the ACE_HANDLE.
109 ACE_Event_Handler
*event_handler_
;
114 * @class ACE_Select_Reactor_Notify
116 * @brief Unblock the ACE_Select_Reactor from its event loop.
118 * This implementation is necessary for cases where the
119 * ACE_Select_Reactor is run in a multi-threaded program. In
120 * this case, we need to be able to unblock @c select or @c poll
121 * when updates occur other than in the main
122 * ACE_Select_Reactor thread. To do this, we signal an
123 * auto-reset event the ACE_Select_Reactor is listening on.
124 * If an ACE_Event_Handler and ACE_Select_Reactor_Mask is
125 * passed to @c notify, the appropriate @c handle_* method is
126 * dispatched in the context of the ACE_Select_Reactor thread.
128 class ACE_Export ACE_Select_Reactor_Notify
: public ACE_Reactor_Notify
132 ACE_Select_Reactor_Notify (void);
135 virtual ~ACE_Select_Reactor_Notify (void);
138 virtual int open (ACE_Reactor_Impl
*,
139 ACE_Timer_Queue
* = 0,
140 int disable_notify_pipe
= ACE_DISABLE_NOTIFY_PIPE_DEFAULT
);
143 virtual int close (void);
146 * Called by a thread when it wants to unblock the
147 * ACE_Select_Reactor. This wakeups the ACE_Select_Reactor if
148 * currently blocked in @c select/poll. Pass over both the
149 * @c Event_Handler *and* the @c mask to allow the caller to dictate
150 * which @c Event_Handler method the ACE_Select_Reactor will
151 * invoke. The ACE_Time_Value indicates how long to blocking
152 * trying to notify the ACE_Select_Reactor. If @a timeout == 0,
153 * the caller will block until action is possible, else will wait
154 * until the relative time specified in @c *timeout elapses).
156 virtual int notify (ACE_Event_Handler
* = 0,
157 ACE_Reactor_Mask
= ACE_Event_Handler::EXCEPT_MASK
,
158 ACE_Time_Value
* timeout
= 0);
160 /// Handles pending threads (if any) that are waiting to unblock the
161 /// ACE_Select_Reactor.
162 virtual int dispatch_notifications (int &number_of_active_handles
,
163 ACE_Handle_Set
&rd_mask
);
165 /// Returns the ACE_HANDLE of the notify pipe on which the reactor
166 /// is listening for notifications so that other threads can unblock
167 /// the Select_Reactor
168 virtual ACE_HANDLE
notify_handle (void);
170 /// Handle one of the notify call on the @c handle. This could be
171 /// because of a thread trying to unblock the Reactor_Impl
172 virtual int dispatch_notify (ACE_Notification_Buffer
&buffer
);
174 /// Read one of the notify call on the @a handle into the
175 /// @a buffer. This could be because of a thread trying to unblock
178 /// Return value semantics for this are:
179 /// -1: nothing read, fatal, unrecoverable error
180 /// 0: nothing read at all
181 /// 1: complete buffer read
182 virtual int read_notify_pipe (ACE_HANDLE handle
,
183 ACE_Notification_Buffer
&buffer
);
185 /// Verify whether the buffer has dispatchable info or not.
186 virtual int is_dispatchable (ACE_Notification_Buffer
&buffer
);
188 /// Called back by the ACE_Select_Reactor when a thread wants to
190 virtual int handle_input (ACE_HANDLE handle
);
193 * Set the maximum number of times that the
194 * ACE_Select_Reactor_Notify::handle_input() method will iterate and
195 * dispatch the ACE_Event_Handlers that are passed in via the
196 * notify pipe before breaking out of its @c recv loop. By default,
197 * this is set to -1, which means "iterate until the pipe is empty."
198 * Setting this to a value like "1 or 2" will increase "fairness"
199 * (and thus prevent starvation) at the expense of slightly higher
200 * dispatching overhead.
202 virtual void max_notify_iterations (int);
205 * Get the maximum number of times that the
206 * ACE_Select_Reactor_Notify::handle_input() method will iterate and
207 * dispatch the ACE_Event_Handlers that are passed in via the
208 * notify pipe before breaking out of its recv loop.
210 virtual int max_notify_iterations (void);
213 * Purge any notifications pending in this reactor for the specified
214 * ACE_Event_Handler object. If @a eh == 0, all notifications for all
215 * handlers are removed (but not any notifications posted just to wake up
216 * the reactor itself). Returns the number of notifications purged.
217 * Returns -1 on error.
219 virtual int purge_pending_notifications (
220 ACE_Event_Handler
*sh
,
221 ACE_Reactor_Mask mask
= ACE_Event_Handler::ALL_EVENTS_MASK
);
223 /// Dump the state of an object.
224 virtual void dump () const;
226 /// Declare the dynamic allocation hooks.
227 ACE_ALLOC_HOOK_DECLARE
;
231 * Keep a back pointer to the ACE_Select_Reactor. If this value
232 * if NULL then the ACE_Select_Reactor has been initialized with
233 * disable_notify_pipe.
235 ACE_Select_Reactor_Impl
*select_reactor_
;
238 * Contains the ACE_HANDLE the ACE_Select_Reactor is listening
239 * on, as well as the ACE_HANDLE that threads wanting the
240 * attention of the ACE_Select_Reactor will write to.
242 ACE_Pipe notification_pipe_
;
245 * Keeps track of the maximum number of times that the
246 * ACE_Select_Reactor_Notify::handle_input() method will iterate and
247 * dispatch the ACE_Event_Handlers that are passed in via the
248 * notify pipe before breaking out of its recv loop. By default,
249 * this is set to -1, which means "iterate until the pipe is empty."
251 int max_notify_iterations_
;
253 #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE)
255 * @brief A user-space queue to store the notifications.
257 * The notification pipe has OS-specific size restrictions. That
258 * is, no more than a certain number of bytes may be stored in the
259 * pipe without blocking. This limit may be too small for certain
260 * applications. In this case, ACE can be configured to store all
261 * the events in user-space. The pipe is still needed to wake up
262 * the reactor thread, but only one event is sent through the pipe
265 ACE_Notification_Queue notification_queue_
;
266 #endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */
270 * @class ACE_Select_Reactor_Handler_Repository
272 * @brief Used to map ACE_HANDLEs onto the appropriate
273 * ACE_Event_Handler *.
275 * This class is necessary to shield differences between UNIX
276 * and Win32. In UNIX, ACE_HANDLE is an int, whereas in Win32
277 * it's a void *. This class hides all these details from the
278 * bulk of the ACE_Select_Reactor code. All of these methods
279 * are called with the main <Select_Reactor> token lock held.
281 class ACE_Export ACE_Select_Reactor_Handler_Repository
284 friend class ACE_Select_Reactor_Handler_Repository_Iterator
;
286 typedef ACE_HANDLE key_type
;
287 typedef ACE_Event_Handler
* value_type
;
289 // = The mapping from <HANDLES> to <Event_Handlers>.
290 #ifdef ACE_SELECT_REACTOR_BASE_USES_HASH_MAP
292 * The NT version implements this via a hash map
293 * @c ACE_Event_Handler*. Since NT implements @c ACE_HANDLE
294 * as a void * we can't directly index into this array. Therefore,
295 * we must explicitly map @c ACE_HANDLE to @c ACE_Event_Handler.
297 typedef ACE_Hash_Map_Manager_Ex
<key_type
,
300 std::equal_to
<key_type
>,
301 ACE_Null_Mutex
> map_type
;
303 typedef map_type::size_type max_handlep1_type
;
306 * The UNIX version implements this via a dynamically allocated
307 * array of @c ACE_Event_Handler* that is indexed directly using
308 * the @c ACE_HANDLE value.
310 typedef ACE_Array_Base
<value_type
> map_type
;
311 typedef ACE_HANDLE max_handlep1_type
;
312 #endif /* ACE_SELECT_REACTOR_BASE_USES_HASH_MAP */
314 typedef map_type::size_type size_type
;
316 /// Default "do-nothing" constructor.
317 ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor_Impl
&);
319 /// Initialize a repository of the appropriate @a size.
321 * On Unix platforms, the size parameter should be as large as the
322 * maximum number of file descriptors allowed for a given process.
323 * This is necessary since a file descriptor is used to directly
324 * index the array of event handlers maintained by the Reactor's
325 * handler repository. Direct indexing is used for efficiency
328 int open (size_type size
);
330 /// Close down the repository.
333 // = Search structure operations.
336 * Return the @c ACE_Event_Handler* associated with @c ACE_HANDLE.
338 ACE_Event_Handler
* find (ACE_HANDLE handle
);
340 /// Bind the ACE_Event_Handler * to the ACE_HANDLE with the
341 /// appropriate ACE_Reactor_Mask settings.
342 int bind (ACE_HANDLE
,
346 /// Remove the binding of ACE_HANDLE in accordance with the @a mask.
347 int unbind (ACE_HANDLE
,
348 ACE_Reactor_Mask mask
);
350 /// Remove all the <ACE_HANDLE, ACE_Event_Handler> tuples.
351 int unbind_all (void);
353 // = Sanity checking.
355 // Check the @a handle to make sure it's a valid @c ACE_HANDLE that
356 // is within the range of legal handles (i.e., >= 0 && < max_size_).
357 bool invalid_handle (ACE_HANDLE handle
);
359 // Check the @a handle to make sure it's a valid @c ACE_HANDLE that
360 // within the range of currently registered handles (i.e., >= 0 && <
361 // @c max_handlep1_).
362 bool handle_in_range (ACE_HANDLE handle
);
365 /// Returns the current table size.
366 size_type
size (void) const;
368 /// Maximum ACE_HANDLE value, plus 1.
369 max_handlep1_type
max_handlep1 (void) const;
371 /// Dump the state of an object.
374 /// Declare the dynamic allocation hooks.
375 ACE_ALLOC_HOOK_DECLARE
;
379 /// Remove the binding of @a handle corresponding to position @a pos
380 /// in accordance with the @a mask.
381 int unbind (ACE_HANDLE handle
,
382 map_type::iterator pos
,
383 ACE_Reactor_Mask mask
);
386 * @return @c iterator corresponding @c ACE_Event_Handler*
387 * associated with @c ACE_HANDLE.
389 map_type::iterator
find_eh (ACE_HANDLE handle
);
392 /// Reference to our @c Select_Reactor.
393 ACE_Select_Reactor_Impl
&select_reactor_
;
395 #ifndef ACE_SELECT_REACTOR_BASE_USES_HASH_MAP
396 /// The highest currently active handle, plus 1 (ranges between 0 and
398 max_handlep1_type max_handlep1_
;
399 #endif /* !ACE_SELECT_REACTOR_BASE_USES_HASH_MAP */
401 /// Underlying table of event handlers.
402 map_type event_handlers_
;
406 * @class ACE_Select_Reactor_Handler_Repository_Iterator
408 * @brief Iterate through the ACE_Select_Reactor_Handler_Repository.
410 class ACE_Export ACE_Select_Reactor_Handler_Repository_Iterator
415 ACE_Select_Reactor_Handler_Repository::map_type::const_iterator const_base_iterator
;
417 explicit ACE_Select_Reactor_Handler_Repository_Iterator (
418 ACE_Select_Reactor_Handler_Repository
const * s
);
420 // = Iteration methods.
422 /// Pass back the @a next_item that hasn't been seen in the Set.
423 /// Returns @c false when all items have been seen, else @c true.
424 bool next (ACE_Event_Handler
* & next_item
);
426 /// Returns @c true when all items have been seen, else @c false.
427 bool done (void) const;
429 /// Move forward by one element in the set. Returns @c false when
430 /// all the items in the set have been seen, else @c true.
433 /// Dump the state of an object.
436 /// Declare the dynamic allocation hooks.
437 ACE_ALLOC_HOOK_DECLARE
;
441 /// Reference to the Handler_Repository we are iterating over.
442 ACE_Select_Reactor_Handler_Repository
const * const rep_
;
444 /// Pointer to the current iteration level.
445 const_base_iterator current_
;
449 * @class ACE_Select_Reactor_Impl
451 * @brief This class simply defines how Select_Reactor's basic interface
452 * functions should look like and provides a common base class for
453 * @c Select_Reactor using various locking mechanism.
455 class ACE_Export ACE_Select_Reactor_Impl
: public ACE_Reactor_Impl
460 /// Default size of the Select_Reactor's handle table.
461 DEFAULT_SIZE
= ACE_DEFAULT_SELECT_REACTOR_SIZE
465 ACE_Select_Reactor_Impl (bool mask_signals
= true);
467 friend class ACE_Select_Reactor_Notify
;
468 friend class ACE_Select_Reactor_Handler_Repository
;
471 * Purge any notifications pending in this reactor for the specified
472 * ACE_Event_Handler object. Returns the number of notifications
473 * purged. Returns -1 on error.
475 virtual int purge_pending_notifications (ACE_Event_Handler
* = 0,
476 ACE_Reactor_Mask
= ACE_Event_Handler::ALL_EVENTS_MASK
);
478 /// Does the reactor allow the application to resume the handle on
479 /// its own ie. can it pass on the control of handle resumption to
480 /// the application. The select reactor has no handlers that can be
481 /// resumed by the application. So return 0;
482 virtual int resumable_handler (void);
485 /// Allow manipulation of the <wait_set_> mask and <ready_set_> mask.
486 virtual int bit_ops (ACE_HANDLE handle
,
487 ACE_Reactor_Mask mask
,
488 ACE_Select_Reactor_Handle_Set
&handle_set
,
491 /// Enqueue ourselves into the list of waiting threads at the
492 /// appropriate point specified by <requeue_position_>.
493 virtual void renew (void) = 0;
495 /// Check to see if the Event_Handler associated with @a handle is
496 /// suspended. Returns 0 if not, 1 if so.
497 virtual int is_suspended_i (ACE_HANDLE handle
) = 0;
499 /// When register/unregister occur, then we need to re-eval our
500 /// wait/suspend/dispatch set.
501 virtual void clear_dispatch_mask (ACE_HANDLE handle
,
502 ACE_Reactor_Mask mask
);
504 /// Table that maps <ACE_HANDLEs> to <ACE_Event_Handler *>'s.
505 ACE_Select_Reactor_Handler_Repository handler_rep_
;
507 /// Tracks handles that are ready for dispatch from <select>
508 ACE_Select_Reactor_Handle_Set dispatch_set_
;
510 /// Tracks handles that are waited for by <select>.
511 ACE_Select_Reactor_Handle_Set wait_set_
;
513 /// Tracks handles that are currently suspended.
514 ACE_Select_Reactor_Handle_Set suspend_set_
;
516 /// Track HANDLES we are interested in for various events that must
517 /// be dispatched *without* going through <select>.
518 ACE_Select_Reactor_Handle_Set ready_set_
;
520 /// Defined as a pointer to allow overriding by derived classes...
521 ACE_Timer_Queue
*timer_queue_
;
523 /// Handle signals without requiring global/static variables.
524 ACE_Sig_Handler
*signal_handler_
;
526 /// Callback object that unblocks the ACE_Select_Reactor if it's
528 ACE_Reactor_Notify
*notify_handler_
;
530 /// Keeps track of whether we should delete the timer queue (if we
531 /// didn't create it, then we don't delete it).
532 bool delete_timer_queue_
;
534 /// Keeps track of whether we should delete the signal handler (if we
535 /// didn't create it, then we don't delete it).
536 bool delete_signal_handler_
;
538 /// Keeps track of whether we need to delete the notify handler (if
539 /// we didn't create it, then we don't delete it).
540 bool delete_notify_handler_
;
542 /// True if we've been initialized yet...
545 /// Restart the <handle_events> event-loop method automatically when
546 /// <select> is interrupted via <EINTR>.
550 * Position that the main ACE_Select_Reactor thread is requeued in
551 * the list of waiters during a <notify> callback. If this value ==
552 * -1 we are requeued at the end of the list. Else if it's 0 then
553 * we are requeued at the front of the list. Else if it's > 1 then
554 * that indicates the number of waiters to skip over.
556 int requeue_position_
;
558 /// The original thread that created this Select_Reactor.
562 * True if state has changed during dispatching of
563 * ACE_Event_Handlers, else false. This is used to determine
564 * whether we need to make another trip through the
565 * <Select_Reactor>'s <wait_for_multiple_events> loop.
570 * If false then the Reactor will not mask the signals during the event
571 * dispatching. This is useful for applications that do not
572 * register any signal handlers and want to reduce the overhead
573 * introduce by the kernel level locks required to change the mask.
577 /// Controls/access whether the notify handler should renew the
578 /// Select_Reactor's token or not.
579 bool supress_notify_renew (void);
580 void supress_notify_renew (bool sr
);
583 /// Determine whether we should renew Select_Reactor's token after handling
584 /// the notification message.
587 /// Deny access since member-wise won't work...
588 ACE_Select_Reactor_Impl (const ACE_Select_Reactor_Impl
&);
589 ACE_Select_Reactor_Impl
&operator = (const ACE_Select_Reactor_Impl
&);
592 ACE_END_VERSIONED_NAMESPACE_DECL
594 #if defined (__ACE_INLINE__)
595 #include "ace/Select_Reactor_Base.inl"
596 #endif /* __ACE_INLINE__ */
598 #include /**/ "ace/post.h"
600 #endif /* ACE_SELECT_REACTOR_BASE_H */