3 //=============================================================================
7 * @author Irfan Pyarali <irfan@cs.wustl.edu>
8 * @author Tim Harrison <harrison@cs.wustl.edu>
9 * @author Alexander Babu Arulanthu <alex@cs.wustl.edu>
10 * @author Alexander Libman <alibman@ihug.com.au>
12 //=============================================================================
14 #ifndef ACE_PROACTOR_H
15 #define ACE_PROACTOR_H
17 #include /**/ "ace/pre.h"
19 #include /**/ "ace/config-all.h"
20 #include /**/ "ace/ACE_export.h"
22 #if !defined (ACE_LACKS_PRAGMA_ONCE)
24 #endif /* ACE_LACKS_PRAGMA_ONCE */
26 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
27 // This only works on Win32 platforms and on Unix platforms supporting
30 # include "ace/Asynch_IO.h"
31 # include "ace/Asynch_IO_Impl.h"
32 # include "ace/Thread_Manager.h"
33 # include "ace/Timer_Queue.h"
34 # include "ace/Timer_List.h"
35 # include "ace/Timer_Heap.h"
36 # include "ace/Timer_Wheel.h"
38 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
40 // Forward declarations.
41 class ACE_Proactor_Impl
;
42 class ACE_Proactor_Timer_Handler
;
44 /// Type def for the timer queue.
45 typedef ACE_Abstract_Timer_Queue
<ACE_Handler
*> ACE_Proactor_Timer_Queue
;
48 * @class ACE_Proactor_Handle_Timeout_Upcall
50 * @brief Functor for ACE_Timer_Queue.
52 * This class implements the functor required by the Timer
53 * Queue to call <handle_timeout> on ACE_Handlers.
55 class ACE_Export ACE_Proactor_Handle_Timeout_Upcall
57 /// The main Proactor class has special permissions.
58 friend class ACE_Proactor
;
62 ACE_Proactor_Handle_Timeout_Upcall ();
64 /// This method is called when a timer is registered.
65 int registration (ACE_Proactor_Timer_Queue
&timer_queue
,
69 /// This method is called before the timer expires.
70 int preinvoke (ACE_Proactor_Timer_Queue
&timer_queue
,
74 const ACE_Time_Value
&cur_time
,
75 const void *&upcall_act
);
77 /// This method is called when the timer expires.
78 int timeout (ACE_Proactor_Timer_Queue
&timer_queue
,
82 const ACE_Time_Value
&cur_time
);
84 /// This method is called after the timer expires.
85 int postinvoke (ACE_Proactor_Timer_Queue
&timer_queue
,
89 const ACE_Time_Value
&cur_time
,
90 const void *upcall_act
);
92 /// This method is called when a handler is canceled.
93 int cancel_type (ACE_Proactor_Timer_Queue
&timer_queue
,
95 int dont_call_handle_close
,
96 int &requires_reference_counting
);
98 /// This method is called when a timer is canceled.
99 int cancel_timer (ACE_Proactor_Timer_Queue
&timer_queue
,
100 ACE_Handler
*handler
,
101 int dont_call_handle_close
,
102 int requires_reference_counting
);
104 /// This method is called when the timer queue is destroyed and the
105 /// timer is still contained in it.
106 int deletion (ACE_Proactor_Timer_Queue
&timer_queue
,
107 ACE_Handler
*handler
,
111 /// Set the proactor. This will fail, if one is already set!
112 int proactor (ACE_Proactor
&proactor
);
114 /// Handle to the proactor. This is needed for posting a timer result
115 /// to the Proactor's completion queue.
116 ACE_Proactor
*proactor_
;
120 * @class ACE_Proactor
122 * @brief A manager for asynchronous event demultiplexing.
124 * See the Proactor pattern description at
125 * http://www.dre.vanderbilt.edu/~schmidt/PDF/proactor.pdf for more
128 class ACE_Export ACE_Proactor
130 // = Here are the private typedefs that the ACE_Proactor uses.
132 typedef ACE_Timer_Queue_Iterator_T
<ACE_Handler
*>
133 TIMER_QUEUE_ITERATOR
;
134 typedef ACE_Timer_List_T
<ACE_Handler
*,
135 ACE_Proactor_Handle_Timeout_Upcall
,
136 ACE_SYNCH_RECURSIVE_MUTEX
>
138 typedef ACE_Timer_List_Iterator_T
<ACE_Handler
*,
139 ACE_Proactor_Handle_Timeout_Upcall
,
140 ACE_SYNCH_RECURSIVE_MUTEX
>
142 typedef ACE_Timer_Heap_T
<ACE_Handler
*,
143 ACE_Proactor_Handle_Timeout_Upcall
,
144 ACE_SYNCH_RECURSIVE_MUTEX
>
146 typedef ACE_Timer_Heap_Iterator_T
<ACE_Handler
*,
147 ACE_Proactor_Handle_Timeout_Upcall
,
148 ACE_SYNCH_RECURSIVE_MUTEX
>
150 typedef ACE_Timer_Wheel_T
<ACE_Handler
*,
151 ACE_Proactor_Handle_Timeout_Upcall
,
152 ACE_SYNCH_RECURSIVE_MUTEX
>
154 typedef ACE_Timer_Wheel_Iterator_T
<ACE_Handler
*,
155 ACE_Proactor_Handle_Timeout_Upcall
,
156 ACE_SYNCH_RECURSIVE_MUTEX
>
157 TIMER_WHEEL_ITERATOR
;
161 /// Timer handler runs a thread and manages the timers, on behalf of
163 friend class ACE_Proactor_Timer_Handler
;
167 * Constructor. If @a implementation is 0, the correct implementation
168 * object will be created. @a delete_implementation flag determines
169 * whether the implementation object should be deleted by the
170 * Proactor or not. If @a tq is 0, a new TIMER_QUEUE is created.
172 ACE_Proactor (ACE_Proactor_Impl
*implementation
= 0,
173 bool delete_implementation
= false,
174 ACE_Proactor_Timer_Queue
*tq
= 0);
179 /// Get pointer to a process-wide ACE_Proactor. @a threads should
180 /// be part of another method.
181 static ACE_Proactor
*instance (size_t threads
= 0);
183 /// Set pointer to a process-wide ACE_Proactor and return existing
185 static ACE_Proactor
*instance (ACE_Proactor
* proactor
,
186 bool delete_proactor
= false);
188 /// Delete the dynamically allocated Singleton.
189 static void close_singleton ();
191 /// Cleanup method, used by the ACE_Object_Manager to destroy the
193 static void cleanup (void *instance
, void *arg
);
195 /// Name of dll in which the singleton instance lives.
196 static const ACE_TCHAR
*dll_name ();
198 /// Name of component--ACE_Proactor in this case.
199 static const ACE_TCHAR
*name ();
201 // = Proactor event loop management methods.
203 /// Run the event loop until the <ACE_Proactor::handle_events> method
204 /// returns -1 or the <end_event_loop> method is invoked.
205 static int run_event_loop ();
208 * Run the event loop until the <ACE_Proactor::handle_events> method
209 * returns -1, the <end_event_loop> method is invoked, or the
210 * ACE_Time_Value expires, in which case 0 is returned.
212 static int run_event_loop (ACE_Time_Value
&tv
);
215 * Instruct the <ACE_Proactor::instance> to terminate its event
217 * This method wakes up all the threads blocked on waiting for
218 * completions and end the event loop.
220 static int end_event_loop ();
223 * Resets the <ACE_Proactor::end_event_loop_> static so that the
224 * <run_event_loop> method can be restarted.
226 static int reset_event_loop ();
229 * The singleton proactor is used by the ACE_Service_Config.
230 * Therefore, we must check for the reconfiguration request and
231 * handle it after handling an event.
233 static int check_reconfiguration (ACE_Proactor
*);
235 /// Report if the <ACE_Proactor::instance> event loop is finished.
236 static int event_loop_done ();
238 /// Close the associated @c ACE_Proactor_Impl implementation object.
240 * If @arg delete_implementation was specified to the @c open() method,
241 * the implementation object is also deleted.
246 * You can add a hook to various run_event methods and the hook will
247 * be called after handling every proactor event. If this function
248 * returns 0, proactor_run_event_loop will check for the return value of
249 * handle_events. If it is -1, the the proactor_run_event_loop will return
252 typedef int (*PROACTOR_EVENT_HOOK
)(ACE_Proactor
*);
254 // These methods work with an instance of a proactor.
256 * Run the event loop until the
257 * <ACE_Proactor::handle_events>
258 * method returns -1 or the <end_proactor_event_loop> method is invoked.
260 int proactor_run_event_loop (PROACTOR_EVENT_HOOK
= 0);
263 * Run the event loop until the <ACE_Proactor::handle_events>
264 * method returns -1, the
265 * <end_proactor_event_loop> method is invoked,
266 * or the ACE_Time_Value
267 * expires, in which case a 0 is returned.
269 int proactor_run_event_loop (ACE_Time_Value
&tv
,
270 PROACTOR_EVENT_HOOK
= 0);
273 * Instruct the ACE_Proactor to terminate its event loop
274 * and notifies the ACE_Proactor so that it can wake up
275 * and close down gracefully.
277 int proactor_end_event_loop ();
279 /// Report if the ACE_Proactor event loop is finished.
280 int proactor_event_loop_done ();
282 /// Resets the <ACE_Proactor::end_event_loop_> static so that the
283 /// <run_event_loop> method can be restarted.
284 int proactor_reset_event_loop ();
287 /// This method adds the @a handle to the I/O completion port. This
288 /// function is a no-op function for Unix systems and returns 0;
289 int register_handle (ACE_HANDLE handle
,
290 const void *completion_key
);
292 // = Timer management.
294 * Schedule a @a handler that will expire after <time>. If it
295 * expires then @a act is passed in as the value to the @a handler's
296 * <handle_timeout> callback method. This method returns a
297 * <timer_id>. This <timer_id> can be used to cancel a timer before
298 * it expires. The cancellation ensures that <timer_ids> are unique
299 * up to values of greater than 2 billion timers. As long as timers
300 * don't stay around longer than this there should be no problems
301 * with accidentally deleting the wrong timer. Returns -1 on
302 * failure (which is guaranteed never to be a valid <timer_id>).
304 long schedule_timer (ACE_Handler
&handler
,
306 const ACE_Time_Value
&time
);
308 long schedule_repeating_timer (ACE_Handler
&handler
,
310 const ACE_Time_Value
&interval
);
312 /// Same as above except @a interval it is used to reschedule the
313 /// @a handler automatically.
315 /// This combines the above two methods into one. Mostly for backward
317 long schedule_timer (ACE_Handler
&handler
,
319 const ACE_Time_Value
&time
,
320 const ACE_Time_Value
&interval
);
322 /// Cancel all timers associated with this @a handler. Returns number
323 /// of timers cancelled.
324 int cancel_timer (ACE_Handler
&handler
,
325 int dont_call_handle_close
= 1);
328 * Cancel the single <ACE_Handler> that matches the @a timer_id value
329 * (which was returned from the <schedule> method). If @a act is
330 * non-NULL then it will be set to point to the ``magic cookie''
331 * argument passed in when the <Handler> was registered. This makes
332 * it possible to free up the memory and avoid memory leaks.
333 * Returns 1 if cancellation succeeded and 0 if the @a timer_id
336 int cancel_timer (long timer_id
,
337 const void **act
= 0,
338 int dont_call_handle_close
= 1);
341 * Dispatch a single set of events, waiting up to a specified time limit
343 * @param wait_time the time to wait for an event to occur. This is
344 * a relative time. On successful return, the time is updated to
345 * reflect the amount of time spent waiting for event(s) to occur.
346 * @return Returns 0 if no events occur before the @a wait_time expires.
347 * Returns 1 when a completion is dispatched. On error, returns -1
348 * and sets errno accordingly.
350 int handle_events (ACE_Time_Value
&wait_time
);
353 * Block indefinitely until at least one event is dispatched.
354 * @return Returns 1 when a completion is dispatched. On error, returns -1
355 * and sets errno accordingly.
357 int handle_events ();
359 /// Add wakeup dispatch threads (reinit).
360 int wake_up_dispatch_threads ();
362 /// Close all dispatch threads.
363 int close_dispatch_threads (int wait
);
365 /// Get number of thread used as a parameter to CreatIoCompletionPort.
366 size_t number_of_threads () const;
368 /// Set number of thread used as a parameter to CreatIoCompletionPort.
369 void number_of_threads (size_t threads
);
372 ACE_Proactor_Timer_Queue
*timer_queue () const;
375 void timer_queue (ACE_Proactor_Timer_Queue
*timer_queue
);
378 * Get the event handle.
379 * It is a no-op in POSIX platforms and it returns
380 * ACE_INVALID_HANDLE.
382 ACE_HANDLE
get_handle () const;
384 /// Get the implementation class.
385 ACE_Proactor_Impl
*implementation () const;
387 // = Factory methods for the operations
389 // Note that the user does not have to use or know about these
392 /// Create the correct implementation class for doing
393 /// Asynch_Read_Stream.
394 ACE_Asynch_Read_Stream_Impl
*create_asynch_read_stream ();
396 /// Create the correct implementation class for doing
397 /// Asynch_Write_Stream.
398 ACE_Asynch_Write_Stream_Impl
*create_asynch_write_stream ();
400 /// Create the correct implementation class for doing
401 /// Asynch_Read_File.
402 ACE_Asynch_Read_File_Impl
*create_asynch_read_file ();
404 /// Create the correct implementation class for doing
405 /// Asynch_Write_File.
406 ACE_Asynch_Write_File_Impl
*create_asynch_write_file ();
408 /// Create the correct implementation class for doing Asynch_Accept.
409 ACE_Asynch_Accept_Impl
*create_asynch_accept ();
411 /// Create the correct implementation class for doing Asynch_Connect.
412 ACE_Asynch_Connect_Impl
*create_asynch_connect ();
414 /// Create the correct implementation class for doing
415 /// Asynch_Transmit_File.
416 ACE_Asynch_Transmit_File_Impl
*create_asynch_transmit_file ();
418 /// Create the correct implementation class for doing
419 /// Asynch_Read_Dgram.
420 ACE_Asynch_Read_Dgram_Impl
*create_asynch_read_dgram ();
422 /// Create the correct implementation class for doing
423 /// Asynch_Write_Dgram.
424 ACE_Asynch_Write_Dgram_Impl
*create_asynch_write_dgram ();
426 // = Factory methods for the results
428 // Note that the user does not have to use or know about these
429 // methods unless they want to "fake" results.
431 /// Create the correct implementation class for
432 /// ACE_Asynch_Read_Stream::Result class.
433 ACE_Asynch_Read_Stream_Result_Impl
*
434 create_asynch_read_stream_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
436 ACE_Message_Block
&message_block
,
437 u_long bytes_to_read
,
439 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
441 int signal_number
= ACE_SIGRTMIN
);
443 /// Create the correct implementation class for
444 /// ACE_Asynch_Write_Stream::Result.
445 ACE_Asynch_Write_Stream_Result_Impl
*
446 create_asynch_write_stream_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
448 ACE_Message_Block
&message_block
,
449 u_long bytes_to_write
,
451 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
453 int signal_number
= ACE_SIGRTMIN
);
455 /// Create the correct implementation class for
456 /// ACE_Asynch_Read_File::Result.
457 ACE_Asynch_Read_File_Result_Impl
*
458 create_asynch_read_file_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
460 ACE_Message_Block
&message_block
,
461 u_long bytes_to_read
,
465 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
467 int signal_number
= ACE_SIGRTMIN
);
469 /// Create the correct implementation class for
470 /// ACE_Asynch_Write_File::Result.
471 ACE_Asynch_Write_File_Result_Impl
*
472 create_asynch_write_file_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
474 ACE_Message_Block
&message_block
,
475 u_long bytes_to_write
,
479 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
481 int signal_number
= ACE_SIGRTMIN
);
483 /// Create the correct implementation class for
484 /// ACE_Asynch_Read_Dgram::Result.
485 ACE_Asynch_Read_Dgram_Result_Impl
*
486 create_asynch_read_dgram_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
488 ACE_Message_Block
*message_block
,
489 size_t bytes_to_read
,
493 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
495 int signal_number
= ACE_SIGRTMIN
);
497 /// Create the correct implementation class for
498 /// ACE_Asynch_Write_Dgram::Result.
499 ACE_Asynch_Write_Dgram_Result_Impl
*
500 create_asynch_write_dgram_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
502 ACE_Message_Block
*message_block
,
503 size_t bytes_to_write
,
506 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
508 int signal_number
= ACE_SIGRTMIN
);
510 /// Create the correct implementation class for ACE_Asynch_Accept::Result.
511 ACE_Asynch_Accept_Result_Impl
*
512 create_asynch_accept_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
513 ACE_HANDLE listen_handle
,
514 ACE_HANDLE accept_handle
,
515 ACE_Message_Block
&message_block
,
516 u_long bytes_to_read
,
518 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
520 int signal_number
= ACE_SIGRTMIN
);
522 /// Create the correct implementation class for ACE_Asynch_Connect::Result
523 ACE_Asynch_Connect_Result_Impl
*
524 create_asynch_connect_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
525 ACE_HANDLE connect_handle
,
527 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
529 int signal_number
= ACE_SIGRTMIN
);
531 /// Create the correct implementation class for
532 /// ACE_Asynch_Transmit_File::Result.
533 ACE_Asynch_Transmit_File_Result_Impl
*
534 create_asynch_transmit_file_result (ACE_Handler::Proxy_Ptr
&handler_proxy
,
537 ACE_Asynch_Transmit_File::Header_And_Trailer
*header_and_trailer
,
538 u_long bytes_to_write
,
541 u_long bytes_per_send
,
544 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
546 int signal_number
= ACE_SIGRTMIN
);
549 * Create a timer result object which can be used with the Timer
550 * mechanism of the Proactor.
551 * If @a signal_number is -1, <POSIX_SIG_Proactor> will create a
552 * Timer object with a meaningful signal number, choosing the
553 * largest signal number from the signal mask of the Proactor.
555 ACE_Asynch_Result_Impl
*
556 create_asynch_timer (ACE_Handler::Proxy_Ptr
&handler_proxy
,
558 const ACE_Time_Value
&tv
,
559 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
561 int signal_number
= ACE_SIGRTMIN
);
565 * Post <how_many> completions to the completion port so that all
566 * threads can wake up. This is used in conjunction with the
569 static int post_wakeup_completions (int how_many
);
572 * Post <how_many> completions to the completion port so that all
573 * threads can wake up. This is used in conjunction with the
574 * <proactor_run_event_loop>.
576 int proactor_post_wakeup_completions (int how_many
);
578 /// Set the implementation class.
579 void implementation (ACE_Proactor_Impl
*implementation
);
581 /// Delegation/implementation class that all methods will be
583 ACE_Proactor_Impl
*implementation_
;
585 /// Flag used to indicate whether we are responsible for cleaning up
586 /// the implementation instance.
587 bool delete_implementation_
;
589 /// Pointer to a process-wide ACE_Proactor.
590 static ACE_Proactor
*proactor_
;
592 /// Must delete the <proactor_> if true.
593 static bool delete_proactor_
;
595 /// Handles timeout events.
596 ACE_Proactor_Timer_Handler
*timer_handler_
;
598 /// This will manage the thread in the Timer_Handler.
599 ACE_Thread_Manager thr_mgr_
;
602 ACE_Proactor_Timer_Queue
*timer_queue_
;
604 /// Flag on whether to delete the timer queue.
605 int delete_timer_queue_
;
607 /// Terminate the proactor event loop.
608 sig_atomic_t end_event_loop_
;
610 /// Number of threads in the event loop.
611 sig_atomic_t event_loop_thread_count_
;
613 /// Mutex to protect work with lists.
614 ACE_SYNCH_MUTEX mutex_
;
618 /// Deny access since member-wise won't work...
619 ACE_Proactor (const ACE_Proactor
&);
620 ACE_Proactor
&operator= (const ACE_Proactor
&);
623 ACE_END_VERSIONED_NAMESPACE_DECL
625 # if defined (__ACE_INLINE__)
626 # include "ace/Proactor.inl"
627 # endif /* __ACE_INLINE__ */
629 #else /* NOT WIN32 or POSIX with AIO features. */
631 # include "ace/os_include/os_stddef.h"
632 # include "ace/os_include/os_signal.h"
634 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
636 class ACE_Time_Value
;
638 class ACE_Export ACE_Proactor
641 class Timer_Queue
{};
642 ACE_Proactor (size_t /* number_of_threads */ = 0,
643 Timer_Queue
* /* tq */ = 0) {}
645 int handle_events () { return -1; }
646 int handle_events (ACE_Time_Value
&) { return -1; }
648 /// Placeholder to enable compilation on non-Win32 platforms
649 static ACE_Proactor
*instance (size_t threads
= 0);
651 /// Placeholder to enable compilation on non-Win32 platforms
652 static ACE_Proactor
*instance (ACE_Proactor
*);
654 /// Placeholder to enable compilation on non-Win32 platforms
655 static void close_singleton ();
657 /// Placeholder to enable compilation on non-Win32 platforms
658 static int run_event_loop ();
660 /// Placeholder to enable compilation on non-Win32 platforms
661 static int run_event_loop (ACE_Time_Value
&tv
);
663 /// Placeholder to enable compilation on non-Win32 platforms
664 static int end_event_loop ();
666 /// Placeholder to enable compilation on non-Win32 platforms
667 static sig_atomic_t event_loop_done ();
670 ACE_END_VERSIONED_NAMESPACE_DECL
672 #endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
674 #include /**/ "ace/post.h"
676 #endif /* ACE_PROACTOR_H */