3 //=============================================================================
5 * @file POSIX_Proactor.h
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 Roger Tragin <r.tragin@computer.org>
11 * @author Alexander Libman <alibman@baltimore.com>
13 //=============================================================================
15 #ifndef ACE_POSIX_PROACTOR_H
16 #define ACE_POSIX_PROACTOR_H
18 #include /**/ "ace/config-all.h"
20 #if !defined (ACE_LACKS_PRAGMA_ONCE)
22 #endif /* ACE_LACKS_PRAGMA_ONCE */
24 #if defined (ACE_HAS_AIO_CALLS)
25 // POSIX implementation of Proactor depends on the <aio_> family of
28 #include "ace/Proactor_Impl.h"
29 #include "ace/Free_List.h"
31 #include "ace/POSIX_Asynch_IO.h"
32 #include "ace/Asynch_Pseudo_Task.h"
34 #define ACE_AIO_MAX_SIZE 2048
35 #define ACE_AIO_DEFAULT_SIZE 1024
37 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
40 * @class ACE_POSIX_Proactor
42 * @brief POSIX implementation of the Proactor.
44 * There are two different strategies by which Proactor can get
45 * to know the completion of <aio> operations. One is based on
46 * Asynchronous I/O Control Blocks (AIOCB) where a list of
47 * AIOCBs are stored and completion status of the corresponding
48 * operations are queried on them. The other one is based on
49 * POSIX Real Time signals. This class abstracts out the common
50 * code needed for both the strategies. ACE_POSIX_AIOCB_Proactor and
51 * ACE_POSIX_SIG_Proactor specialize this class for each strategy.
53 class ACE_Export ACE_POSIX_Proactor
: public ACE_Proactor_Impl
61 /// Aio_suspend() based
64 /// Signals notifications
67 /// Callback notifications
72 enum SystemType
// open for future extention
74 ACE_OS_UNDEFINED
= 0x0000,
75 ACE_OS_WIN
= 0x0100, // for future
76 ACE_OS_WIN_NT
= ACE_OS_WIN
| 0x0001,
77 ACE_OS_WIN_2000
= ACE_OS_WIN
| 0x0002,
78 ACE_OS_LINUX
= 0x0800, // Linux family
79 ACE_OS_FREEBSD
= 0x1000, // FreeBSD family
80 ACE_OS_IRIX
= 0x2000, // SGI IRIX family
81 ACE_OS_OPENBSD
= 0x4000 // OpenBSD familty
89 virtual Proactor_Type
get_impl_type ();
91 /// Virtual destructor.
92 virtual ~ACE_POSIX_Proactor ();
94 /// Close down the Proactor.
98 * Dispatch a single set of events. If @a wait_time elapses before
99 * any events occur, return 0. Return 1 on success i.e., when a
100 * completion is dispatched, non-zero (-1) on errors and errno is
103 virtual int handle_events (ACE_Time_Value
&wait_time
) = 0;
106 * Block indefinitely until at least one event is dispatched.
107 * Dispatch a single set of events.Return 1 on success i.e., when a
108 * completion is dispatched, non-zero (-1) on errors and errno is
111 virtual int handle_events () = 0;
114 * Post a result to the completion port of the Proactor. If errors
115 * occur, the result will be deleted by this method. If successful,
116 * the result will be deleted by the Proactor when the result is
117 * removed from the completion port. Therefore, the result should
118 * have been dynamically allocated and should be orphaned by the
119 * user once this method is called.
121 virtual int post_completion (ACE_POSIX_Asynch_Result
*result
) = 0;
123 virtual int start_aio (ACE_POSIX_Asynch_Result
*result
, Opcode op
) = 0;
125 virtual int cancel_aio (ACE_HANDLE h
) = 0;
127 /// Task to process pseudo-asynchronous operations
128 ACE_Asynch_Pseudo_Task
&get_asynch_pseudo_task ();
130 /// This function is a no-op function for Unix systems. Returns 0.
131 virtual int register_handle (ACE_HANDLE handle
,
132 const void *completion_key
);
134 /// @@ This is a no-op on POSIX platforms. Returns 0.
135 int wake_up_dispatch_threads ();
137 /// @@ This is a no-op on POSIX platforms. Returns 0.
138 int close_dispatch_threads (int wait
);
140 /// @@ This is a no-op on POSIX platforms. Returns 0.
141 size_t number_of_threads () const;
142 void number_of_threads (size_t threads
);
144 /// This is a no-op in POSIX. Returns ACE_INVALID_HANDLE.
145 virtual ACE_HANDLE
get_handle () const;
147 // Methods used to create Asynch IO factory and result objects. We
148 // create the right objects here in these methods.
150 virtual ACE_Asynch_Read_Stream_Impl
*create_asynch_read_stream ();
151 virtual ACE_Asynch_Read_Stream_Result_Impl
*
152 create_asynch_read_stream_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
154 ACE_Message_Block
&message_block
,
155 size_t bytes_to_read
,
157 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
159 int signal_number
= ACE_SIGRTMIN
);
161 virtual ACE_Asynch_Write_Stream_Impl
*create_asynch_write_stream ();
162 virtual ACE_Asynch_Write_Stream_Result_Impl
*
163 create_asynch_write_stream_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
165 ACE_Message_Block
&message_block
,
166 size_t bytes_to_write
,
168 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
170 int signal_number
= ACE_SIGRTMIN
);
172 virtual ACE_Asynch_Read_File_Impl
*create_asynch_read_file ();
173 virtual ACE_Asynch_Read_File_Result_Impl
*
174 create_asynch_read_file_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
176 ACE_Message_Block
&message_block
,
177 size_t bytes_to_read
,
181 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
183 int signal_number
= ACE_SIGRTMIN
);
185 virtual ACE_Asynch_Write_File_Impl
*create_asynch_write_file ();
186 virtual ACE_Asynch_Write_File_Result_Impl
*
187 create_asynch_write_file_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
189 ACE_Message_Block
&message_block
,
190 size_t bytes_to_write
,
194 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
196 int signal_number
= ACE_SIGRTMIN
);
198 virtual ACE_Asynch_Read_Dgram_Impl
*create_asynch_read_dgram ();
199 virtual ACE_Asynch_Read_Dgram_Result_Impl
*
200 create_asynch_read_dgram_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
202 ACE_Message_Block
*message_block
,
203 size_t bytes_to_read
,
207 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
209 int signal_number
= ACE_SIGRTMIN
);
211 virtual ACE_Asynch_Write_Dgram_Impl
*create_asynch_write_dgram ();
212 virtual ACE_Asynch_Write_Dgram_Result_Impl
*
213 create_asynch_write_dgram_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
215 ACE_Message_Block
*message_block
,
216 size_t bytes_to_write
,
219 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
221 int signal_number
= ACE_SIGRTMIN
);
223 virtual ACE_Asynch_Accept_Impl
*create_asynch_accept ();
224 virtual ACE_Asynch_Accept_Result_Impl
*
225 create_asynch_accept_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
226 ACE_HANDLE listen_handle
,
227 ACE_HANDLE accept_handle
,
228 ACE_Message_Block
&message_block
,
229 size_t bytes_to_read
,
231 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
233 int signal_number
= ACE_SIGRTMIN
);
235 virtual ACE_Asynch_Connect_Impl
*create_asynch_connect ();
236 virtual ACE_Asynch_Connect_Result_Impl
*
237 create_asynch_connect_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
238 ACE_HANDLE connect_handle
,
240 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
242 int signal_number
= ACE_SIGRTMIN
);
244 virtual ACE_Asynch_Transmit_File_Impl
*create_asynch_transmit_file ();
245 virtual ACE_Asynch_Transmit_File_Result_Impl
*
246 create_asynch_transmit_file_result (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
249 ACE_Asynch_Transmit_File::Header_And_Trailer
*header_and_trailer
,
250 size_t bytes_to_write
,
253 size_t bytes_per_send
,
256 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
258 int signal_number
= ACE_SIGRTMIN
);
260 /// Create a timer result object which can be used with the Timer
261 /// mechanism of the Proactor.
262 virtual ACE_Asynch_Result_Impl
*
263 create_asynch_timer (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
265 const ACE_Time_Value
&tv
,
266 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
268 int signal_number
= ACE_SIGRTMIN
);
272 ACE_POSIX_Proactor ();
275 * Protect against structured exceptions caused by user code when
276 * dispatching handles. The <completion_key> is not very useful
277 * compared to <AST> that can be associated each asynchronous
278 * operation. <completion_key> is implemented right now for the
281 void application_specific_code (ACE_POSIX_Asynch_Result
*asynch_result
,
282 size_t bytes_transferred
,
283 const void *completion_key
,
287 * Post <how_many> completions to the completion port so that all
288 * threads can wake up. This is used in conjunction with the
291 virtual int post_wakeup_completions (int how_many
);
294 /// Handler to handle the wakeups. This works in conjunction with the
295 /// <ACE_Proactor::run_event_loop>.
296 ACE_Handler wakeup_handler_
;
300 /// Task to process pseudo-asynchronous accept/connect
301 ACE_Asynch_Pseudo_Task pseudo_task_
;
304 // Forward declarations.
305 class ACE_AIOCB_Notify_Pipe_Manager
;
308 * @class ACE_POSIX_AIOCB_Proactor
310 * @brief This Proactor makes use of Asynchronous I/O Control Blocks
311 * (AIOCB) to notify/get the completion status of the <aio_>
314 class ACE_Export ACE_POSIX_AIOCB_Proactor
: public ACE_POSIX_Proactor
316 /// Handler needs to call application specific code.
317 friend class ACE_AIOCB_Notify_Pipe_Manager
;
319 /// This class does the registering of Asynch Operations with the
320 /// Proactor which is necessary in the AIOCB strategy.
321 friend class ACE_POSIX_Asynch_Operation
;
322 friend class ACE_POSIX_Asynch_Accept
;
323 friend class ACE_POSIX_Asynch_Connect
;
327 /// Constructor defines max number asynchronous operations
328 /// which can be started at the same time
329 ACE_POSIX_AIOCB_Proactor (size_t nmaxop
= ACE_AIO_DEFAULT_SIZE
);
331 virtual Proactor_Type
get_impl_type ();
334 virtual ~ACE_POSIX_AIOCB_Proactor ();
336 /// Close down the Proactor.
337 virtual int close ();
340 * Dispatch a single set of events. If @a wait_time elapses before
341 * any events occur, return 0. Return 1 on success i.e., when a
342 * completion is dispatched, non-zero (-1) on errors and errno is
345 virtual int handle_events (ACE_Time_Value
&wait_time
);
348 * Block indefinitely until at least one event is dispatched.
349 * Dispatch a single set of events. If @a wait_time elapses before
350 * any events occur, return 0. Return 1 on success i.e., when a
351 * completion is dispatched, non-zero (-1) on errors and errno is
354 virtual int handle_events ();
356 /// Post a result to the completion port of the Proactor.
357 virtual int post_completion (ACE_POSIX_Asynch_Result
*result
);
359 virtual int start_aio (ACE_POSIX_Asynch_Result
*result
,
360 ACE_POSIX_Proactor::Opcode op
);
363 * This method should be called from
364 * ACE_POSIX_Asynch_Operation::cancel()
365 * instead of usual ::aio_cancel.
366 * For all deferred AIO requests with handle "h"
367 * it removes its from the lists and notifies user.
368 * For all running AIO requests with handle "h"
369 * it calls ::aio_cancel. According to the POSIX standards
370 * we will receive ECANCELED for all ::aio_canceled AIO requests
371 * later on return from ::aio_suspend
373 virtual int cancel_aio (ACE_HANDLE h
);
376 /// Special constructor for ACE_SUN_Proactor
377 /// and ACE_POSIX_SIG_Proactor
378 ACE_POSIX_AIOCB_Proactor (size_t nmaxop
,
379 ACE_POSIX_Proactor::Proactor_Type ptype
);
381 /// Check AIO for completion, error and result status
382 /// Return: 1 - AIO completed , 0 - not completed yet
383 virtual int get_result_status (ACE_POSIX_Asynch_Result
*asynch_result
,
385 size_t &transfer_count
);
387 /// Create aiocb list
388 int create_result_aiocb_list ();
390 /// Call this method from derived class when virtual table is
392 int delete_result_aiocb_list ();
394 /// Call these methods from derived class when virtual table is
396 void create_notify_manager ();
397 void delete_notify_manager ();
399 /// Define the maximum number of asynchronous I/O requests
400 /// for the current OS
401 void check_max_aio_num ();
403 /// To identify requests from Notify_Pipe_Manager
404 void set_notify_handle (ACE_HANDLE h
);
407 * Dispatch a single set of events. If <milli_seconds> elapses
408 * before any events occur, return 0. Return 1 if a completion
409 * dispatched. Return -1 on errors.
411 int handle_events_i (u_long milli_seconds
);
413 /// Start deferred AIO if necessary
414 int start_deferred_aio ();
416 /// Cancel running or deferred AIO
417 virtual int cancel_aiocb (ACE_POSIX_Asynch_Result
* result
);
419 /// Extract the results of aio.
420 ACE_POSIX_Asynch_Result
*find_completed_aio (int &error_status
,
421 size_t &transfer_count
,
425 /// Find free slot to store result and aiocb pointer
426 virtual ssize_t
allocate_aio_slot (ACE_POSIX_Asynch_Result
*result
);
428 /// Initiate an aio operation.
429 virtual int start_aio_i (ACE_POSIX_Asynch_Result
*result
);
431 /// Notify queue of "post_completed" ACE_POSIX_Asynch_Results
432 /// called from post_completion method
433 virtual int notify_completion (int sig_num
);
435 /// Put "post_completed" result into the internal queue
436 int putq_result (ACE_POSIX_Asynch_Result
*result
);
438 /// Get "post_completed" result from the internal queue
439 ACE_POSIX_Asynch_Result
* getq_result ();
441 /// Clear the internal results queue
442 int clear_result_queue ();
444 /// Process the internal results queue
445 int process_result_queue ();
448 /// This class takes care of doing <accept> when we use
449 /// AIO_CONTROL_BLOCKS strategy.
450 ACE_AIOCB_Notify_Pipe_Manager
*aiocb_notify_pipe_manager_
;
452 /// Use a dynamically allocated array to keep track of all the aio's
453 /// issued currently.
455 ACE_POSIX_Asynch_Result
**result_list_
;
457 /// To maintain the maximum size of the array (list).
458 size_t aiocb_list_max_size_
;
460 /// To maintain the current size of the array (list).
461 size_t aiocb_list_cur_size_
;
463 /// Mutex to protect work with lists.
464 ACE_SYNCH_MUTEX mutex_
;
466 /// The purpose of this member is only to identify asynchronous request
467 /// from NotifyManager. We will reserve for it always slot 0
468 /// in the list of aiocb's to be sure that don't lose notifications.
469 ACE_HANDLE notify_pipe_read_handle_
;
471 /// Number of ACE_POSIX_Asynch_Result's waiting for start
472 /// i.e. deferred AIOs
473 size_t num_deferred_aiocb_
;
475 /// Number active,i.e. running requests
476 size_t num_started_aio_
;
478 /// Queue which keeps "post_completed" ACE_POSIX_Asynch_Result's
479 ACE_Unbounded_Queue
<ACE_POSIX_Asynch_Result
*> result_queue_
;
482 #if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
484 * @class ACE_POSIX_SIG_Proactor
486 * @brief This Proactor implementation does completion event detection using
487 * POSIX Real Time signals. @c sigtimedwait() or @c sigwaitinfo() is
488 * used to wait for completions.
489 * The real-time signals that are going to be used with this
490 * Proactor should be given apriori in the constructor, so that
491 * those signals can be masked from asynchronous delivery.
493 class ACE_Export ACE_POSIX_SIG_Proactor
: public ACE_POSIX_AIOCB_Proactor
496 * This class does the registering of Asynch Operations with the
497 * Proactor which is necessary in the SIG strategy, because we need
498 * to store the signal number.
500 friend class ACE_POSIX_SIG_Asynch_Operation
;
504 * This constructor masks only the <ACE_SIGRTMIN>
505 * real-time signal. Only this signal should be used to issue
506 * asynchronous operations using this Proctor.
508 ACE_POSIX_SIG_Proactor (size_t nmaxop
= ACE_AIO_DEFAULT_SIZE
);
510 virtual Proactor_Type
get_impl_type ();
513 * This constructor should be used to tell the Proactor to mask and
514 * wait for the real-time signals specified in this set. Only these
515 * signals should be used by the asynchronous operations when they
518 ACE_POSIX_SIG_Proactor (const sigset_t mask_set
,
519 size_t nmaxop
= ACE_AIO_DEFAULT_SIZE
);
522 virtual ~ACE_POSIX_SIG_Proactor ();
525 * Dispatch a single set of events. If @a wait_time elapses before
526 * any events occur, return 0. Return 1 on success i.e., when a
527 * completion is dispatched, non-zero (-1) on errors and errno is
530 virtual int handle_events (ACE_Time_Value
&wait_time
);
533 * Block indefinitely until at least one event is dispatched.
534 * Dispatch a single set of events. If <wait_time> elapses before
535 * any events occur, return 0. Return 1 on success i.e., when a
536 * completion is dispatched, non-zero (-1) on errors and errno is
539 virtual int handle_events ();
541 /// Post a result to the completion port of the Proactor.
542 /// now it is implemented in base ACE_POSIX_AIOCB_Proactor class
543 ///virtual int post_completion (ACE_POSIX_Asynch_Result *result);
546 * If @a signal_number is -1, check with the Proactor and use one of
547 * the signals that is present in the mask set (i.e., the signals for
548 * which the Proactor will be waiting) of the Proactor. If there are
549 * more than one signal, the higher numbered signal will be chosen.
551 virtual ACE_Asynch_Result_Impl
*create_asynch_timer
552 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
554 const ACE_Time_Value
&tv
,
555 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
557 int signal_number
= ACE_SIGRTMIN
);
560 /// To setup the handler for a real-time signbal.
561 int setup_signal_handler (int signal_number
) const;
563 /// Insures that RT_completion_signals_ are blocked in the calling thread.
564 int block_signals () const;
567 * Dispatch a single set of events. @a timeout is a pointer to a
568 * relative time representing the maximum amount of time to wait for
569 * an event to occur. If 0, wait indefinitely.
571 * @retval 0 A timeout occurred before any event was detected.
572 * @retval 1 A completion was dispatched.
573 * @retval -1 An error occurred; errno contains an error code.
575 virtual int handle_events_i (const ACE_Time_Value
*timeout
);
577 /// Find free slot to store result and aiocb pointer
578 virtual ssize_t
allocate_aio_slot (ACE_POSIX_Asynch_Result
*result
);
580 /// Notify queue of "post_completed" ACE_POSIX_Asynch_Results
581 /// called from post_completion method
582 virtual int notify_completion (int sig_num
);
585 * These signals are used for completion notification by the
586 * Proactor. The signals specified while issuing asynchronous
587 * operations are stored here in this set. These signals are masked
588 * for a thread when it calls handle_events().
590 sigset_t RT_completion_signals_
;
594 #endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
597 * @class ACE_POSIX_Asynch_Timer
599 * @brief This class is posted to the completion port when a timer
600 * expires. When the @c complete() method of this object is
601 * called, the handler's @c handle_timeout() method will be
604 class ACE_Export ACE_POSIX_Asynch_Timer
: public ACE_POSIX_Asynch_Result
606 /// The factory method for this class is with the POSIX_Proactor
608 friend class ACE_POSIX_Proactor
;
609 #if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
610 friend class ACE_POSIX_SIG_Proactor
;
615 ACE_POSIX_Asynch_Timer (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
617 const ACE_Time_Value
&tv
,
618 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
620 int signal_number
= ACE_SIGRTMIN
);
623 ~ACE_POSIX_Asynch_Timer () override
= default;
625 /// This method calls the handler's handle_timeout method.
626 void complete (size_t bytes_transferred
,
628 const void *completion_key
,
629 u_long error
= 0) override
;
631 /// Time value requested by caller
632 ACE_Time_Value time_
;
635 ACE_END_VERSIONED_NAMESPACE_DECL
637 #if defined (__ACE_INLINE__)
638 #include "ace/POSIX_Proactor.inl"
639 #endif /* __ACE_INLINE__ */
641 #endif /* ACE_HAS_AIO_CALLS && ACE_HAS_POSIX_REALTIME_SIGNALS */
642 #endif /* ACE_POSIX_PROACTOR_H */