Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / POSIX_Proactor.h
blob143e16b269b41199b57392c4f14001a20176d3f5
1 // -*- C++ -*-
3 //=============================================================================
4 /**
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)
21 #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
26 // system calls.
28 #include "ace/Proactor_Impl.h"
29 #include "ace/Free_List.h"
30 #include "ace/Pipe.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
39 /**
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
55 public:
56 enum Proactor_Type
58 /// Base class type
59 PROACTOR_POSIX = 0,
61 /// Aio_suspend() based
62 PROACTOR_AIOCB = 1,
64 /// Signals notifications
65 PROACTOR_SIG = 2,
67 /// Callback notifications
68 PROACTOR_CB = 4
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
84 enum Opcode {
85 ACE_OPCODE_READ = 1,
86 ACE_OPCODE_WRITE = 2
89 virtual Proactor_Type get_impl_type ();
91 /// Virtual destructor.
92 virtual ~ACE_POSIX_Proactor ();
94 /// Close down the Proactor.
95 virtual int close ();
97 /**
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
101 * set accordingly.
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
109 * set accordingly.
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,
153 ACE_HANDLE handle,
154 ACE_Message_Block &message_block,
155 size_t bytes_to_read,
156 const void *act,
157 ACE_HANDLE event = ACE_INVALID_HANDLE,
158 int priority = 0,
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,
164 ACE_HANDLE handle,
165 ACE_Message_Block &message_block,
166 size_t bytes_to_write,
167 const void *act,
168 ACE_HANDLE event = ACE_INVALID_HANDLE,
169 int priority = 0,
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,
175 ACE_HANDLE handle,
176 ACE_Message_Block &message_block,
177 size_t bytes_to_read,
178 const void *act,
179 u_long offset,
180 u_long offset_high,
181 ACE_HANDLE event = ACE_INVALID_HANDLE,
182 int priority = 0,
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,
188 ACE_HANDLE handle,
189 ACE_Message_Block &message_block,
190 size_t bytes_to_write,
191 const void *act,
192 u_long offset,
193 u_long offset_high,
194 ACE_HANDLE event = ACE_INVALID_HANDLE,
195 int priority = 0,
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,
201 ACE_HANDLE handle,
202 ACE_Message_Block *message_block,
203 size_t bytes_to_read,
204 int flags,
205 int protocol_family,
206 const void* act,
207 ACE_HANDLE event = ACE_INVALID_HANDLE,
208 int priority = 0,
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,
214 ACE_HANDLE handle,
215 ACE_Message_Block *message_block,
216 size_t bytes_to_write,
217 int flags,
218 const void* act,
219 ACE_HANDLE event = ACE_INVALID_HANDLE,
220 int priority = 0,
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,
230 const void *act,
231 ACE_HANDLE event = ACE_INVALID_HANDLE,
232 int priority = 0,
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,
239 const void *act,
240 ACE_HANDLE event = ACE_INVALID_HANDLE,
241 int priority = 0,
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,
247 ACE_HANDLE socket,
248 ACE_HANDLE file,
249 ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
250 size_t bytes_to_write,
251 u_long offset,
252 u_long offset_high,
253 size_t bytes_per_send,
254 u_long flags,
255 const void *act,
256 ACE_HANDLE event = ACE_INVALID_HANDLE,
257 int priority = 0,
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,
264 const void *act,
265 const ACE_Time_Value &tv,
266 ACE_HANDLE event = ACE_INVALID_HANDLE,
267 int priority = 0,
268 int signal_number = ACE_SIGRTMIN);
270 protected:
271 /// Constructor.
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
279 * POSIX Proators.
281 void application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,
282 size_t bytes_transferred,
283 const void *completion_key,
284 u_long error);
287 * Post <how_many> completions to the completion port so that all
288 * threads can wake up. This is used in conjunction with the
289 * <run_event_loop>.
291 virtual int post_wakeup_completions (int how_many);
293 protected:
294 /// Handler to handle the wakeups. This works in conjunction with the
295 /// <ACE_Proactor::run_event_loop>.
296 ACE_Handler wakeup_handler_;
297 int os_id_;
299 private:
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_>
312 * operations issued.
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;
326 public:
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 ();
333 /// Destructor.
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
343 * set accordingly.
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
352 * set accordingly.
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);
375 protected:
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,
384 int &error_status,
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
391 /// built.
392 int delete_result_aiocb_list ();
394 /// Call these methods from derived class when virtual table is
395 /// built.
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,
422 size_t &index,
423 size_t &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.
454 aiocb **aiocb_list_;
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;
502 public:
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
516 * use this Proactor.
518 ACE_POSIX_SIG_Proactor (const sigset_t mask_set,
519 size_t nmaxop = ACE_AIO_DEFAULT_SIZE);
521 /// Destructor.
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
528 * set accordingly.
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
537 * set accordingly.
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,
553 const void *act,
554 const ACE_Time_Value &tv,
555 ACE_HANDLE event = ACE_INVALID_HANDLE,
556 int priority = 0,
557 int signal_number = ACE_SIGRTMIN);
559 protected:
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
602 * called.
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
607 /// class.
608 friend class ACE_POSIX_Proactor;
609 #if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
610 friend class ACE_POSIX_SIG_Proactor;
611 #endif
613 protected:
614 /// Constructor.
615 ACE_POSIX_Asynch_Timer (const ACE_Handler::Proxy_Ptr &handler_proxy,
616 const void *act,
617 const ACE_Time_Value &tv,
618 ACE_HANDLE event = ACE_INVALID_HANDLE,
619 int priority = 0,
620 int signal_number = ACE_SIGRTMIN);
622 /// Destructor.
623 ~ACE_POSIX_Asynch_Timer () override = default;
625 /// This method calls the handler's handle_timeout method.
626 void complete (size_t bytes_transferred,
627 int success,
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 */