1 #include "ace/POSIX_Proactor.h"
3 #if defined (ACE_HAS_AIO_CALLS)
5 #if !defined (__ACE_INLINE__)
6 #include "ace/POSIX_Proactor.inl"
7 #endif /* __ACE_INLINE__ */
10 #include "ace/Flag_Manip.h"
11 #include "ace/Task_T.h"
12 #include "ace/Log_Category.h"
13 #include "ace/Object_Manager.h"
14 #include "ace/OS_NS_sys_socket.h"
15 #include "ace/OS_NS_signal.h"
16 #include "ace/OS_NS_unistd.h"
18 // *********************************************************************
20 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
23 * @class ACE_POSIX_Wakeup_Completion
25 * This result object is used by the <end_event_loop> of the
26 * ACE_Proactor interface to wake up all the threads blocking
29 class ACE_POSIX_Wakeup_Completion
: public ACE_POSIX_Asynch_Result
33 ACE_POSIX_Wakeup_Completion (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
35 ACE_HANDLE event
= ACE_INVALID_HANDLE
,
37 int signal_number
= ACE_SIGRTMIN
);
40 ~ACE_POSIX_Wakeup_Completion () override
;
43 /// This method calls the <handler>'s <handle_wakeup> method.
44 void complete (size_t bytes_transferred
= 0,
46 const void *completion_key
= 0,
47 u_long error
= 0) override
;
50 // *********************************************************************
51 ACE_POSIX_Proactor::ACE_POSIX_Proactor ()
52 : os_id_ (ACE_OS_UNDEFINED
)
54 #if defined(__OpenBSD)
55 os_id_
= ACE_OS_OPENBSD
; // set family
58 //#else defined (LINUX, __FreeBSD__ ...)
63 ACE_POSIX_Proactor::~ACE_POSIX_Proactor ()
69 ACE_POSIX_Proactor::close ()
75 ACE_POSIX_Proactor::register_handle (ACE_HANDLE handle
,
76 const void *completion_key
)
78 ACE_UNUSED_ARG (handle
);
79 ACE_UNUSED_ARG (completion_key
);
84 ACE_POSIX_Proactor::wake_up_dispatch_threads ()
90 ACE_POSIX_Proactor::close_dispatch_threads (int)
96 ACE_POSIX_Proactor::number_of_threads () const
99 ACE_NOTSUP_RETURN (0);
103 ACE_POSIX_Proactor::number_of_threads (size_t threads
)
106 ACE_UNUSED_ARG (threads
);
110 ACE_POSIX_Proactor::get_handle () const
112 return ACE_INVALID_HANDLE
;
115 ACE_Asynch_Read_Stream_Impl
*
116 ACE_POSIX_Proactor::create_asynch_read_stream ()
118 ACE_Asynch_Read_Stream_Impl
*implementation
= 0;
119 ACE_NEW_RETURN (implementation
,
120 ACE_POSIX_Asynch_Read_Stream (this),
122 return implementation
;
125 ACE_Asynch_Read_Stream_Result_Impl
*
126 ACE_POSIX_Proactor::create_asynch_read_stream_result
127 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
129 ACE_Message_Block
&message_block
,
130 size_t bytes_to_read
,
136 ACE_Asynch_Read_Stream_Result_Impl
*implementation
;
137 ACE_NEW_RETURN (implementation
,
138 ACE_POSIX_Asynch_Read_Stream_Result (handler_proxy
,
147 return implementation
;
151 ACE_Asynch_Write_Stream_Impl
*
152 ACE_POSIX_Proactor::create_asynch_write_stream ()
154 ACE_Asynch_Write_Stream_Impl
*implementation
= 0;
155 ACE_NEW_RETURN (implementation
,
156 ACE_POSIX_Asynch_Write_Stream (this),
158 return implementation
;
161 ACE_Asynch_Write_Stream_Result_Impl
*
162 ACE_POSIX_Proactor::create_asynch_write_stream_result
163 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
165 ACE_Message_Block
&message_block
,
166 size_t bytes_to_write
,
172 ACE_Asynch_Write_Stream_Result_Impl
*implementation
;
173 ACE_NEW_RETURN (implementation
,
174 ACE_POSIX_Asynch_Write_Stream_Result (handler_proxy
,
183 return implementation
;
187 ACE_Asynch_Read_File_Impl
*
188 ACE_POSIX_Proactor::create_asynch_read_file ()
190 ACE_Asynch_Read_File_Impl
*implementation
= 0;
191 ACE_NEW_RETURN (implementation
,
192 ACE_POSIX_Asynch_Read_File (this),
194 return implementation
;
197 ACE_Asynch_Read_File_Result_Impl
*
198 ACE_POSIX_Proactor::create_asynch_read_file_result
199 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
201 ACE_Message_Block
&message_block
,
202 size_t bytes_to_read
,
210 ACE_Asynch_Read_File_Result_Impl
*implementation
;
211 ACE_NEW_RETURN (implementation
,
212 ACE_POSIX_Asynch_Read_File_Result (handler_proxy
,
223 return implementation
;
227 ACE_Asynch_Write_File_Impl
*
228 ACE_POSIX_Proactor::create_asynch_write_file ()
230 ACE_Asynch_Write_File_Impl
*implementation
= 0;
231 ACE_NEW_RETURN (implementation
,
232 ACE_POSIX_Asynch_Write_File (this),
234 return implementation
;
237 ACE_Asynch_Write_File_Result_Impl
*
238 ACE_POSIX_Proactor::create_asynch_write_file_result
239 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
241 ACE_Message_Block
&message_block
,
242 size_t bytes_to_write
,
250 ACE_Asynch_Write_File_Result_Impl
*implementation
;
251 ACE_NEW_RETURN (implementation
,
252 ACE_POSIX_Asynch_Write_File_Result (handler_proxy
,
263 return implementation
;
267 ACE_Asynch_Read_Dgram_Impl
*
268 ACE_POSIX_Proactor::create_asynch_read_dgram ()
270 ACE_Asynch_Read_Dgram_Impl
*implementation
= 0;
271 ACE_NEW_RETURN (implementation
,
272 ACE_POSIX_Asynch_Read_Dgram (this),
274 return implementation
;
277 ACE_Asynch_Read_Dgram_Result_Impl
*
278 ACE_POSIX_Proactor::create_asynch_read_dgram_result
279 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
281 ACE_Message_Block
*message_block
,
282 size_t bytes_to_read
,
290 ACE_Asynch_Read_Dgram_Result_Impl
*implementation
=0;
291 ACE_NEW_RETURN (implementation
,
292 ACE_POSIX_Asynch_Read_Dgram_Result(handler_proxy
,
304 return implementation
;
308 ACE_Asynch_Write_Dgram_Impl
*
309 ACE_POSIX_Proactor::create_asynch_write_dgram ()
311 ACE_Asynch_Write_Dgram_Impl
*implementation
= 0;
312 ACE_NEW_RETURN (implementation
,
313 ACE_POSIX_Asynch_Write_Dgram (this),
316 return implementation
;
319 ACE_Asynch_Write_Dgram_Result_Impl
*
320 ACE_POSIX_Proactor::create_asynch_write_dgram_result
321 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
323 ACE_Message_Block
*message_block
,
324 size_t bytes_to_write
,
331 ACE_Asynch_Write_Dgram_Result_Impl
*implementation
=0;
332 ACE_NEW_RETURN (implementation
,
333 ACE_POSIX_Asynch_Write_Dgram_Result(handler_proxy
,
344 return implementation
;
348 ACE_Asynch_Accept_Impl
*
349 ACE_POSIX_Proactor::create_asynch_accept ()
351 ACE_Asynch_Accept_Impl
*implementation
= 0;
352 ACE_NEW_RETURN (implementation
,
353 ACE_POSIX_Asynch_Accept (this),
356 return implementation
;
359 ACE_Asynch_Accept_Result_Impl
*
360 ACE_POSIX_Proactor::create_asynch_accept_result
361 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
362 ACE_HANDLE listen_handle
,
363 ACE_HANDLE accept_handle
,
364 ACE_Message_Block
&message_block
,
365 size_t bytes_to_read
,
371 ACE_Asynch_Accept_Result_Impl
*implementation
;
372 ACE_NEW_RETURN (implementation
,
373 ACE_POSIX_Asynch_Accept_Result (handler_proxy
,
383 return implementation
;
387 ACE_Asynch_Connect_Impl
*
388 ACE_POSIX_Proactor::create_asynch_connect ()
390 ACE_Asynch_Connect_Impl
*implementation
= 0;
391 ACE_NEW_RETURN (implementation
,
392 ACE_POSIX_Asynch_Connect (this),
395 return implementation
;
398 ACE_Asynch_Connect_Result_Impl
*
399 ACE_POSIX_Proactor::create_asynch_connect_result
400 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
401 ACE_HANDLE connect_handle
,
407 ACE_Asynch_Connect_Result_Impl
*implementation
;
408 ACE_NEW_RETURN (implementation
,
409 ACE_POSIX_Asynch_Connect_Result (handler_proxy
,
416 return implementation
;
420 ACE_Asynch_Transmit_File_Impl
*
421 ACE_POSIX_Proactor::create_asynch_transmit_file ()
423 ACE_Asynch_Transmit_File_Impl
*implementation
= 0;
424 ACE_NEW_RETURN (implementation
,
425 ACE_POSIX_Asynch_Transmit_File (this),
427 return implementation
;
430 ACE_Asynch_Transmit_File_Result_Impl
*
431 ACE_POSIX_Proactor::create_asynch_transmit_file_result
432 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
435 ACE_Asynch_Transmit_File::Header_And_Trailer
*header_and_trailer
,
436 size_t bytes_to_write
,
439 size_t bytes_per_send
,
446 ACE_Asynch_Transmit_File_Result_Impl
*implementation
;
447 ACE_NEW_RETURN (implementation
,
448 ACE_POSIX_Asynch_Transmit_File_Result (handler_proxy
,
462 return implementation
;
465 ACE_Asynch_Result_Impl
*
466 ACE_POSIX_Proactor::create_asynch_timer
467 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
469 const ACE_Time_Value
&tv
,
474 ACE_POSIX_Asynch_Timer
*implementation
;
475 ACE_NEW_RETURN (implementation
,
476 ACE_POSIX_Asynch_Timer (handler_proxy
,
483 return implementation
;
487 ACE_POSIX_Proactor::application_specific_code (ACE_POSIX_Asynch_Result
*asynch_result
,
488 size_t bytes_transferred
,
489 const void */
* completion_key*/
,
494 // Call completion hook
495 asynch_result
->complete (bytes_transferred
,
497 0, // No completion key.
502 // This is crucial to prevent memory leaks
503 delete asynch_result
;
508 ACE_POSIX_Proactor::post_wakeup_completions (int how_many
)
510 ACE_POSIX_Wakeup_Completion
*wakeup_completion
= 0;
512 for (int ci
= 0; ci
< how_many
; ci
++)
516 ACE_POSIX_Wakeup_Completion (this->wakeup_handler_
.proxy ()),
518 if (this->post_completion (wakeup_completion
) == -1)
525 ACE_POSIX_Proactor::Proactor_Type
526 ACE_POSIX_Proactor::get_impl_type ()
528 return PROACTOR_POSIX
;
533 * @class ACE_AIOCB_Notify_Pipe_Manager
535 * @brief This class manages the notify pipe of the AIOCB Proactor.
537 * This class acts as the Handler for the
538 * <Asynch_Read> operations issued on the notify pipe. This
539 * class is very useful in implementing <Asynch_Accept> operation
540 * class for the <AIOCB_Proactor>. This is also useful for
541 * implementing <post_completion> for <AIOCB_Proactor>.
543 * <AIOCB_Proactor> class issues a <Asynch_Read> on
544 * the pipe, using this class as the
545 * Handler. <POSIX_Asynch_Result *>'s are sent through the
546 * notify pipe. When <POSIX_Asynch_Result *>'s show up on the
547 * notify pipe, the <POSIX_AIOCB_Proactor> dispatches the
548 * completion of the <Asynch_Read_Stream> and calls the
549 * <handle_read_stream> of this class. This class calls
550 * <complete> on the <POSIX_Asynch_Result *> and thus calls the
551 * application handler.
552 * Handling the MessageBlock:
553 * We give this message block to read the result pointer through
554 * the notify pipe. We expect that to read 4 bytes from the
555 * notify pipe, for each <accept> call. Before giving this
556 * message block to another <accept>, we update <wr_ptr> and put
557 * it in its initial position.
559 class ACE_AIOCB_Notify_Pipe_Manager
: public ACE_Handler
562 /// Constructor. You need the posix proactor because you need to call
563 /// <application_specific_code>
564 ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor
*posix_aiocb_proactor
);
567 ~ACE_AIOCB_Notify_Pipe_Manager () override
;
569 /// Send the result pointer through the notification pipe.
572 /// This is the call back method when <Asynch_Read> from the pipe is
574 void handle_read_stream (const ACE_Asynch_Read_Stream::Result
&result
) override
;
577 /// The implementation proactor class.
578 ACE_POSIX_AIOCB_Proactor
*posix_aiocb_proactor_
;
580 /// Message block to get ACE_POSIX_Asynch_Result pointer from the pipe.
581 ACE_Message_Block message_block_
;
583 /// Pipe for the communication between Proactor and the
584 /// Asynch_Accept/Asynch_Connect and other post_completions
587 /// To do asynch_read on the pipe.
588 ACE_POSIX_Asynch_Read_Stream read_stream_
;
590 /// Default constructor. Shouldnt be called.
591 ACE_AIOCB_Notify_Pipe_Manager ();
594 ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor
*posix_aiocb_proactor
)
595 : posix_aiocb_proactor_ (posix_aiocb_proactor
),
596 message_block_ (sizeof (2)),
597 read_stream_ (posix_aiocb_proactor
)
600 if (this->pipe_
.open () == -1)
601 ACELIB_ERROR ((LM_ERROR
,
602 ACE_TEXT("%N:%l:%p\n"),
603 ACE_TEXT("ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:")
604 ACE_TEXT("Open of pipe failed")));
606 // Set write side in NONBLOCK mode
607 ACE::set_flags (this->pipe_
.write_handle (), ACE_NONBLOCK
);
609 // Set read side in BLOCK mode
610 ACE::clr_flags (this->pipe_
.read_handle (), ACE_NONBLOCK
);
612 // Let AIOCB_Proactor know about our handle
613 posix_aiocb_proactor_
->set_notify_handle (this->pipe_
.read_handle ());
615 // Open the read stream.
616 if (this->read_stream_
.open (this->proxy (),
617 this->pipe_
.read_handle (),
621 ACELIB_ERROR ((LM_ERROR
,
622 ACE_TEXT("%N:%l:%p\n"),
623 ACE_TEXT("ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:")
624 ACE_TEXT("Open on Read Stream failed")));
626 // Issue an asynch_read on the read_stream of the notify pipe.
627 if (this->read_stream_
.read (this->message_block_
,
628 1, // enough to read 1 byte
632 ACELIB_ERROR ((LM_ERROR
,
633 ACE_TEXT("%N:%l:%p\n"),
634 ACE_TEXT("ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:")
635 ACE_TEXT("Read from pipe failed")));
638 ACE_AIOCB_Notify_Pipe_Manager::~ACE_AIOCB_Notify_Pipe_Manager ()
640 // 1. try to cancel pending aio
641 this->read_stream_
.cancel ();
643 // 2. close both handles
644 // Destuctor of ACE_Pipe does not close handles.
645 // We can not use ACE_Pipe::close() as it
646 // closes read_handle and than write_handle.
647 // In some systems close() may wait for
648 // completion for all asynch. pending requests.
649 // So we should close write_handle firstly
650 // to force read completion ( if 1. does not help )
651 // and then read_handle and not vice versa
653 ACE_HANDLE h
= this->pipe_
.write_handle ();
654 if (h
!= ACE_INVALID_HANDLE
)
655 ACE_OS::closesocket (h
);
657 h
= this->pipe_
.read_handle ();
658 if ( h
!= ACE_INVALID_HANDLE
)
659 ACE_OS::closesocket (h
);
664 ACE_AIOCB_Notify_Pipe_Manager::notify ()
666 // Send the result pointer through the pipe.
668 ssize_t ret_val
= ACE::send (this->pipe_
.write_handle (),
674 if (errno
!= EWOULDBLOCK
)
676 ACELIB_ERROR ((LM_ERROR
,
677 ACE_TEXT ("(%P %t):%p\n"),
678 ACE_TEXT ("ACE_AIOCB_Notify_Pipe_Manager::notify")
679 ACE_TEXT ("Error:Writing on to notify pipe failed")));
688 ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream
689 (const ACE_Asynch_Read_Stream::Result
& /*result*/)
691 // 1. Start new read to avoid pipe overflow
693 // Set the message block properly. Put the <wr_ptr> back in the
695 if (this->message_block_
.length () > 0)
696 this->message_block_
.wr_ptr (this->message_block_
.rd_ptr ());
698 // One accept has completed. Issue a read to handle any
699 // <post_completion>s in the future.
700 if (-1 == this->read_stream_
.read (this->message_block_
,
701 1, // enough to read 1 byte
704 ACELIB_ERROR ((LM_ERROR
,
705 ACE_TEXT ("%N:%l:(%P | %t):%p\n"),
706 ACE_TEXT ("ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream:")
707 ACE_TEXT ("Read from pipe failed")));
711 // this->posix_aiocb_proactor_->process_result_queue ();
714 // Public constructor for common use.
715 ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (size_t max_aio_operations
)
716 : aiocb_notify_pipe_manager_ (0),
719 aiocb_list_max_size_ (max_aio_operations
),
720 aiocb_list_cur_size_ (0),
721 notify_pipe_read_handle_ (ACE_INVALID_HANDLE
),
722 num_deferred_aiocb_ (0),
725 // Check for correct value for max_aio_operations
726 check_max_aio_num ();
728 this->create_result_aiocb_list ();
730 this->create_notify_manager ();
732 // start pseudo-asynchronous accept task
733 // one per all future acceptors
734 this->get_asynch_pseudo_task().start ();
737 // Special protected constructor for ACE_SUN_Proactor
738 ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (size_t max_aio_operations
,
739 ACE_POSIX_Proactor::Proactor_Type
)
740 : aiocb_notify_pipe_manager_ (0),
743 aiocb_list_max_size_ (max_aio_operations
),
744 aiocb_list_cur_size_ (0),
745 notify_pipe_read_handle_ (ACE_INVALID_HANDLE
),
746 num_deferred_aiocb_ (0),
749 //check for correct value for max_aio_operations
750 this->check_max_aio_num ();
752 this->create_result_aiocb_list ();
754 // @@ We should create Notify_Pipe_Manager in the derived class to
755 // provide correct calls for virtual functions !!!
759 ACE_POSIX_AIOCB_Proactor::~ACE_POSIX_AIOCB_Proactor ()
764 ACE_POSIX_Proactor::Proactor_Type
765 ACE_POSIX_AIOCB_Proactor::get_impl_type ()
767 return PROACTOR_AIOCB
;
772 ACE_POSIX_AIOCB_Proactor::close ()
774 // stop asynch accept task
775 this->get_asynch_pseudo_task().stop ();
777 this->delete_notify_manager ();
779 this->clear_result_queue ();
781 return this->delete_result_aiocb_list ();
784 void ACE_POSIX_AIOCB_Proactor::set_notify_handle (ACE_HANDLE h
)
786 notify_pipe_read_handle_
= h
;
789 int ACE_POSIX_AIOCB_Proactor::create_result_aiocb_list ()
791 if (aiocb_list_
!= 0)
794 ACE_NEW_RETURN (aiocb_list_
, aiocb
*[aiocb_list_max_size_
], -1);
796 ACE_NEW_RETURN (result_list_
,
797 ACE_POSIX_Asynch_Result
*[aiocb_list_max_size_
],
800 // Initialize the array.
801 for (size_t ai
= 0; ai
< this->aiocb_list_max_size_
; ai
++)
804 result_list_
[ai
] = 0;
810 int ACE_POSIX_AIOCB_Proactor::delete_result_aiocb_list ()
812 if (aiocb_list_
== 0) // already deleted
817 // Try to cancel all uncompleted operations; POSIX systems may have
818 // hidden system threads that still can work with our aiocbs!
819 for (ai
= 0; ai
< aiocb_list_max_size_
; ai
++)
820 if (this->aiocb_list_
[ai
] != 0) // active operation
821 this->cancel_aiocb (result_list_
[ai
]);
825 for (ai
= 0; ai
< aiocb_list_max_size_
; ai
++)
827 if (this->aiocb_list_
[ai
] == 0 ) // not active operation
830 // Get the error and return status of the aio_ operation.
831 int error_status
= 0;
832 size_t transfer_count
= 0;
833 int flg_completed
= this->get_result_status (result_list_
[ai
],
837 //don't delete uncompleted AIOCB's
838 if (flg_completed
== 0) // not completed !!!
842 char * errtxt
= ACE_OS::strerror (error_status
);
846 char * op
= (aiocb_list_
[ai
]->aio_lio_opcode
== LIO_WRITE
)?
850 ACELIB_ERROR ((LM_ERROR
,
851 ACE_TEXT("slot=%d op=%s status=%d xfercnt=%d %s\n"),
859 else // completed , OK
861 delete this->result_list_
[ai
];
862 this->result_list_
[ai
] = 0;
863 this->aiocb_list_
[ai
] = 0;
867 // If it is not possible cancel some operation (num_pending > 0 ),
868 // we can do only one thing -report about this
869 // and complain about POSIX implementation.
870 // We know that we have memory leaks, but it is better than
871 // segmentation fault!
874 ACE_TEXT("ACE_POSIX_AIOCB_Proactor::delete_result_aiocb_list\n")
875 ACE_TEXT(" number pending AIO=%d\n"),
878 delete [] this->aiocb_list_
;
879 this->aiocb_list_
= 0;
881 delete [] this->result_list_
;
882 this->result_list_
= 0;
884 return (num_pending
== 0 ? 0 : -1);
885 // ?? or just always return 0;
888 void ACE_POSIX_AIOCB_Proactor::check_max_aio_num ()
890 #if !defined (ACE_ANDROID)
891 // Android API 23 introduced a define _POSIX_AIO_MAX 1 which gets used by _SC_AIO_MAX.
892 // Previously, without the define, the value returned was -1, which got ignored.
893 // Officially, the Android OS does not support AIO so if ACE_HAS_AIO_CALLS is defined
894 // then a 3rd party library must be in use and this check is invalid.
896 long max_os_aio_num
= ACE_OS::sysconf (_SC_AIO_MAX
);
898 // Define max limit AIO's for concrete OS
899 // -1 means that there is no limit, but it is not true
900 // (example, SunOS 5.6)
902 if (max_os_aio_num
> 0 &&
903 aiocb_list_max_size_
> (unsigned long) max_os_aio_num
)
904 aiocb_list_max_size_
= max_os_aio_num
;
907 #if defined (__FreeBSD__)
908 long max_os_listio_num
= ACE_OS::sysconf (_SC_AIO_LISTIO_MAX
);
909 if (max_os_listio_num
> 0
910 && aiocb_list_max_size_
> (unsigned long) max_os_listio_num
)
911 aiocb_list_max_size_
= max_os_listio_num
;
912 #endif /* __FreeBSD__ */
914 // check for user-defined value
915 // ACE_AIO_MAX_SIZE if defined in POSIX_Proactor.h
917 if (aiocb_list_max_size_
<= 0
918 || aiocb_list_max_size_
> ACE_AIO_MAX_SIZE
)
919 aiocb_list_max_size_
= ACE_AIO_MAX_SIZE
;
921 // check for max number files to open
923 int max_num_files
= ACE::max_handles ();
925 if (max_num_files
> 0
926 && aiocb_list_max_size_
> (unsigned long) max_num_files
)
928 ACE::set_handle_limit (aiocb_list_max_size_
);
930 max_num_files
= ACE::max_handles ();
933 if (max_num_files
> 0
934 && aiocb_list_max_size_
> (unsigned long) max_num_files
)
935 aiocb_list_max_size_
= (unsigned long) max_num_files
;
937 ACELIB_DEBUG ((LM_DEBUG
,
938 "(%P | %t) ACE_POSIX_AIOCB_Proactor::Max Number of AIOs=%d\n",
939 aiocb_list_max_size_
));
943 ACE_POSIX_AIOCB_Proactor::create_notify_manager ()
945 // Remember! this issues a Asynch_Read
946 // on the notify pipe for doing the Asynch_Accept/Connect.
948 if (aiocb_notify_pipe_manager_
== 0)
949 ACE_NEW (aiocb_notify_pipe_manager_
,
950 ACE_AIOCB_Notify_Pipe_Manager (this));
954 ACE_POSIX_AIOCB_Proactor::delete_notify_manager ()
956 // We are responsible for delete as all pointers set to 0 after
957 // delete, it is save to delete twice
958 delete aiocb_notify_pipe_manager_
;
959 aiocb_notify_pipe_manager_
= 0;
963 ACE_POSIX_AIOCB_Proactor::handle_events (ACE_Time_Value
&wait_time
)
965 // Decrement <wait_time> with the amount of time spent in the method
966 ACE_Countdown_Time
countdown (&wait_time
);
967 return this->handle_events_i (wait_time
.msec ());
971 ACE_POSIX_AIOCB_Proactor::handle_events ()
973 return this->handle_events_i (ACE_INFINITE
);
977 ACE_POSIX_AIOCB_Proactor::notify_completion(int sig_num
)
979 ACE_UNUSED_ARG (sig_num
);
981 return this->aiocb_notify_pipe_manager_
->notify ();
985 ACE_POSIX_AIOCB_Proactor::post_completion (ACE_POSIX_Asynch_Result
*result
)
987 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX
, ace_mon
, this->mutex_
, -1));
989 int ret_val
= this->putq_result (result
);
995 ACE_POSIX_AIOCB_Proactor::putq_result (ACE_POSIX_Asynch_Result
*result
)
997 // this protected method should be called with locked mutex_
998 // we can't use GUARD as Proactor uses non-recursive mutex
1003 int sig_num
= result
->signal_number ();
1004 int ret_val
= this->result_queue_
.enqueue_tail (result
);
1007 ACELIB_ERROR_RETURN ((LM_ERROR
,
1008 "%N:%l:ACE_POSIX_AIOCB_Proactor::putq_result failed\n"),
1011 this->notify_completion (sig_num
);
1016 ACE_POSIX_Asynch_Result
* ACE_POSIX_AIOCB_Proactor::getq_result ()
1018 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX
, ace_mon
, this->mutex_
, 0));
1021 ACE_POSIX_Asynch_Result
* result
= 0;
1023 if (this->result_queue_
.dequeue_head (result
) != 0)
1026 // don't waste time if queue is empty - it is normal
1027 // or check queue size before dequeue_head
1028 // ACELIB_ERROR_RETURN ((LM_ERROR,
1029 // ACE_TEXT("%N:%l:(%P | %t):%p\n"),
1030 // ACE_TEXT("ACE_POSIX_AIOCB_Proactor::getq_result failed")),
1036 int ACE_POSIX_AIOCB_Proactor::clear_result_queue ()
1039 ACE_POSIX_Asynch_Result
* result
= 0;
1041 while ((result
= this->getq_result ()) != 0)
1050 int ACE_POSIX_AIOCB_Proactor::process_result_queue ()
1053 ACE_POSIX_Asynch_Result
* result
= 0;
1055 while ((result
= this->getq_result ()) != 0)
1057 this->application_specific_code
1059 result
->bytes_transferred(), // 0, No bytes transferred.
1060 0, // No completion key.
1061 result
->error()); //0, No error.
1070 ACE_POSIX_AIOCB_Proactor::handle_events_i (u_long milli_seconds
)
1072 int result_suspend
= 0;
1075 if (milli_seconds
== ACE_INFINITE
)
1076 // Indefinite blocking.
1077 result_suspend
= aio_suspend (aiocb_list_
,
1078 aiocb_list_max_size_
,
1082 // Block on <aio_suspend> for <milli_seconds>
1084 timeout
.tv_sec
= milli_seconds
/ 1000;
1085 timeout
.tv_nsec
= (milli_seconds
- (timeout
.tv_sec
* 1000)) * 1000000;
1086 result_suspend
= aio_suspend (aiocb_list_
,
1087 aiocb_list_max_size_
,
1092 if (result_suspend
== -1)
1094 if (errno
!= EAGAIN
&& // Timeout
1095 errno
!= EINTR
) // Interrupted call
1096 ACELIB_ERROR ((LM_ERROR
,
1097 ACE_TEXT ("%N:%l:(%P|%t)::%p\n"),
1098 ACE_TEXT ("handle_events: aio_suspend failed")));
1099 // let continue work
1100 // we should check "post_completed" queue
1105 size_t count
= aiocb_list_max_size_
; // max number to iterate
1106 int error_status
= 0;
1107 size_t transfer_count
= 0;
1111 ACE_POSIX_Asynch_Result
*asynch_result
=
1112 find_completed_aio (error_status
,
1117 if (asynch_result
== 0)
1120 // Call the application code.
1121 this->application_specific_code (asynch_result
,
1123 0, // No completion key.
1128 // process post_completed results
1129 retval
+= this->process_result_queue ();
1131 return retval
> 0 ? 1 : 0;
1135 ACE_POSIX_AIOCB_Proactor::get_result_status (ACE_POSIX_Asynch_Result
*asynch_result
,
1137 size_t &transfer_count
)
1141 // Get the error status of the aio_ operation.
1142 // The following aio_ptr anathema is required to work around a bug in an over-aggressive
1143 // optimizer in GCC 4.1.2.
1144 aiocb
*aio_ptr (asynch_result
);
1145 error_status
= aio_error (aio_ptr
);
1146 if (error_status
== EINPROGRESS
)
1147 return 0; // not completed
1149 ssize_t op_return
= aio_return (aio_ptr
);
1151 transfer_count
= static_cast<size_t> (op_return
);
1152 // else transfer_count is already 0, error_status reports the error.
1153 return 1; // completed
1156 ACE_POSIX_Asynch_Result
*
1157 ACE_POSIX_AIOCB_Proactor::find_completed_aio (int &error_status
,
1158 size_t &transfer_count
,
1162 // parameter index defines initial slot to scan
1163 // parameter count tells us how many slots should we scan
1165 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->mutex_
, 0));
1167 ACE_POSIX_Asynch_Result
*asynch_result
= 0;
1169 if (num_started_aio_
== 0) // save time
1172 for (; count
> 0; index
++ , count
--)
1174 if (index
>= aiocb_list_max_size_
) // like a wheel
1177 if (aiocb_list_
[index
] == 0) // Dont process null blocks.
1180 if (0 != this->get_result_status (result_list_
[index
],
1182 transfer_count
)) // completed
1186 if (count
== 0) // all processed , nothing found
1188 asynch_result
= result_list_
[index
];
1190 aiocb_list_
[index
] = 0;
1191 result_list_
[index
] = 0;
1192 aiocb_list_cur_size_
--;
1194 num_started_aio_
--; // decrement count active aios
1195 index
++; // for next iteration
1196 count
--; // for next iteration
1198 this->start_deferred_aio ();
1199 //make attempt to start deferred AIO
1200 //It is safe as we are protected by mutex_
1202 return asynch_result
;
1207 ACE_POSIX_AIOCB_Proactor::start_aio (ACE_POSIX_Asynch_Result
*result
,
1208 ACE_POSIX_Proactor::Opcode op
)
1210 ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_aio");
1212 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->mutex_
, -1));
1214 int ret_val
= (aiocb_list_cur_size_
>= aiocb_list_max_size_
) ? -1 : 0;
1216 if (result
== 0) // Just check the status of the list
1219 // Save operation code in the aiocb
1222 case ACE_POSIX_Proactor::ACE_OPCODE_READ
:
1223 result
->aio_lio_opcode
= LIO_READ
;
1226 case ACE_POSIX_Proactor::ACE_OPCODE_WRITE
:
1227 result
->aio_lio_opcode
= LIO_WRITE
;
1231 ACELIB_ERROR_RETURN ((LM_ERROR
,
1232 ACE_TEXT ("%N:%l:(%P|%t)::")
1233 ACE_TEXT ("start_aio: Invalid op code %d\n"),
1238 if (ret_val
!= 0) // No free slot
1244 // Find a free slot and store.
1246 ssize_t slot
= allocate_aio_slot (result
);
1251 size_t index
= static_cast<size_t> (slot
);
1253 result_list_
[index
] = result
; //Store result ptr anyway
1254 aiocb_list_cur_size_
++;
1256 ret_val
= start_aio_i (result
);
1259 case 0: // started OK
1260 aiocb_list_
[index
] = result
;
1263 case 1: // OS AIO queue overflow
1264 num_deferred_aiocb_
++;
1267 default: // Invalid request, there is no point
1268 break; // to start it later
1271 result_list_
[index
] = 0;
1272 aiocb_list_cur_size_
--;
1277 ACE_POSIX_AIOCB_Proactor::allocate_aio_slot (ACE_POSIX_Asynch_Result
*result
)
1281 // we reserve zero slot for ACE_AIOCB_Notify_Pipe_Manager
1282 // so make check for ACE_AIOCB_Notify_Pipe_Manager request
1284 if (notify_pipe_read_handle_
== result
->aio_fildes
) // Notify_Pipe ?
1285 { // should be free,
1286 if (result_list_
[i
] != 0) // only 1 request
1289 ACELIB_ERROR_RETURN ((LM_ERROR
,
1290 "%N:%l:(%P | %t)::\n"
1291 "ACE_POSIX_AIOCB_Proactor::allocate_aio_slot:"
1292 "internal Proactor error 0\n"),
1296 else //try to find free slot as usual, but starting from 1
1298 for (i
= 1; i
< this->aiocb_list_max_size_
; i
++)
1299 if (result_list_
[i
] == 0)
1303 if (i
>= this->aiocb_list_max_size_
)
1304 ACELIB_ERROR_RETURN ((LM_ERROR
,
1305 "%N:%l:(%P | %t)::\n"
1306 "ACE_POSIX_AIOCB_Proactor::allocate_aio_slot:"
1307 "internal Proactor error 1\n"),
1310 //setup OS notification methods for this aio
1311 result
->aio_sigevent
.sigev_notify
= SIGEV_NONE
;
1313 return static_cast<ssize_t
> (i
);
1316 // start_aio_i has new return codes
1317 // 0 AIO was started successfully
1318 // 1 AIO was not started, OS AIO queue overflow
1319 // -1 AIO was not started, other errors
1322 ACE_POSIX_AIOCB_Proactor::start_aio_i (ACE_POSIX_Asynch_Result
*result
)
1324 ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_aio_i");
1327 const ACE_TCHAR
*ptype
= 0;
1330 // The following aio_ptr anathema is required to work around a bug in
1331 // the optimizer for GCC 4.1.2
1332 aiocb
* aio_ptr (result
);
1333 switch (result
->aio_lio_opcode
)
1336 ptype
= ACE_TEXT ("read ");
1337 ret_val
= aio_read (aio_ptr
);
1340 ptype
= ACE_TEXT ("write");
1341 ret_val
= aio_write (aio_ptr
);
1344 ptype
= ACE_TEXT ("?????");
1351 ++this->num_started_aio_
;
1353 else // if (ret_val == -1)
1355 if (errno
== EAGAIN
|| errno
== ENOMEM
) //Ok, it will be deferred AIO
1358 ACELIB_ERROR ((LM_ERROR
,
1359 ACE_TEXT ("%N:%l:(%P | %t)::start_aio_i: aio_%s %p\n"),
1361 ACE_TEXT ("queueing failed")));
1369 ACE_POSIX_AIOCB_Proactor::start_deferred_aio ()
1371 ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_deferred_aio");
1373 // This protected method is called from
1374 // find_completed_aio after any AIO completion
1375 // We should call this method always with locked
1376 // ACE_POSIX_AIOCB_Proactor::mutex_
1378 // It tries to start the first deferred AIO
1381 if (num_deferred_aiocb_
== 0)
1382 return 0; // nothing to do
1386 for (i
= 0; i
< this->aiocb_list_max_size_
; i
++)
1387 if (result_list_
[i
] !=0 // check for
1388 && aiocb_list_
[i
] ==0) // deferred AIO
1391 if (i
>= this->aiocb_list_max_size_
)
1392 ACELIB_ERROR_RETURN ((LM_ERROR
,
1393 "%N:%l:(%P | %t)::\n"
1394 "start_deferred_aio:"
1395 "internal Proactor error 3\n"),
1398 ACE_POSIX_Asynch_Result
*result
= result_list_
[i
];
1400 int ret_val
= start_aio_i (result
);
1404 case 0 : //started OK , decrement count of deferred AIOs
1405 aiocb_list_
[i
] = result
;
1406 num_deferred_aiocb_
--;
1410 return 0; //try again later
1412 default : // Invalid Parameters , should never be
1418 result_list_
[i
] = 0;
1419 --aiocb_list_cur_size_
;
1421 --num_deferred_aiocb_
;
1423 result
->set_error (errno
);
1424 result
->set_bytes_transferred (0);
1425 this->putq_result (result
); // we are with locked mutex_ here !
1431 ACE_POSIX_AIOCB_Proactor::cancel_aio (ACE_HANDLE handle
)
1433 // This new method should be called from
1434 // ACE_POSIX_Asynch_Operation instead of usual ::aio_cancel
1435 // It scans the result_list_ and defines all AIO requests
1436 // that were issued for handle "handle"
1438 // For all deferred AIO requests with handle "handle"
1439 // it removes its from the lists and notifies user
1441 // For all running AIO requests with handle "handle"
1442 // it calls ::aio_cancel. According to the POSIX standards
1443 // we will receive ECANCELED for all ::aio_canceled AIO requests
1444 // later on return from ::aio_suspend
1446 ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::cancel_aio");
1449 int num_cancelled
= 0;
1452 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->mutex_
, -1));
1456 for (ai
= 0; ai
< this->aiocb_list_max_size_
; ai
++)
1458 if (this->result_list_
[ai
] == 0) // Skip empty slot
1461 if (this->result_list_
[ai
]->aio_fildes
!= handle
) // Not ours
1466 ACE_POSIX_Asynch_Result
*asynch_result
= this->result_list_
[ai
];
1468 if (this->aiocb_list_
[ai
] == 0) // Canceling a deferred operation
1471 this->num_deferred_aiocb_
--;
1473 this->aiocb_list_
[ai
] = 0;
1474 this->result_list_
[ai
] = 0;
1475 this->aiocb_list_cur_size_
--;
1477 asynch_result
->set_error (ECANCELED
);
1478 asynch_result
->set_bytes_transferred (0);
1479 this->putq_result (asynch_result
);
1480 // we are with locked mutex_ here !
1482 else // Cancel started aio
1484 int rc_cancel
= this->cancel_aiocb (asynch_result
);
1486 if (rc_cancel
== 0) //notification in the future
1487 num_cancelled
++; //it is OS responsiblity
1494 return 1; // ALLDONE
1496 if (num_cancelled
== num_total
)
1497 return 0; // CANCELLED
1499 return 2; // NOT CANCELLED
1503 ACE_POSIX_AIOCB_Proactor::cancel_aiocb (ACE_POSIX_Asynch_Result
* result
)
1505 // This method is called from cancel_aio
1506 // to cancel a previously submitted AIO request
1507 int rc
= ::aio_cancel (0, result
);
1509 // Check the return value and return 0/1/2 appropriately.
1510 if (rc
== AIO_CANCELED
)
1512 else if (rc
== AIO_ALLDONE
)
1514 else // (rc == AIO_NOTCANCELED)
1519 // *********************************************************************
1521 #if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
1523 ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (size_t max_aio_operations
)
1524 : ACE_POSIX_AIOCB_Proactor (max_aio_operations
,
1525 ACE_POSIX_Proactor::PROACTOR_SIG
)
1527 // = Set up the mask we'll use to block waiting for SIGRTMIN. Use that
1528 // to add it to the signal mask for this thread, and also set the process
1529 // signal action to pass signal information when we want it.
1531 // Clear the signal set.
1532 ACE_OS::sigemptyset (&this->RT_completion_signals_
);
1534 // Add the signal number to the signal set.
1535 if (ACE_OS::sigaddset (&this->RT_completion_signals_
, ACE_SIGRTMIN
) == -1)
1536 ACELIB_ERROR ((LM_ERROR
, ACE_TEXT ("ACE_POSIX_SIG_Proactor: %p\n"),
1537 ACE_TEXT ("sigaddset")));
1538 this->block_signals ();
1539 // Set up the signal action for SIGRTMIN.
1540 this->setup_signal_handler (ACE_SIGRTMIN
);
1542 // we do not have to create notify manager
1543 // but we should start pseudo-asynchronous accept task
1544 // one per all future acceptors
1546 this->get_asynch_pseudo_task().start ();
1550 ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (const sigset_t signal_set
,
1551 size_t max_aio_operations
)
1552 : ACE_POSIX_AIOCB_Proactor (max_aio_operations
,
1553 ACE_POSIX_Proactor::PROACTOR_SIG
)
1555 // = Keep <Signal_set> with the Proactor, mask all the signals and
1556 // setup signal actions for the signals in the <signal_set>.
1558 // = Keep <signal_set> with the Proactor.
1560 // Empty the signal set first.
1561 if (sigemptyset (&this->RT_completion_signals_
) == -1)
1562 ACELIB_ERROR ((LM_ERROR
,
1563 ACE_TEXT("Error:(%P | %t):%p\n"),
1564 ACE_TEXT("sigemptyset failed")));
1566 // For each signal number present in the <signal_set>, add it to
1567 // the signal set we use, and also set up its process signal action
1568 // to allow signal info to be passed into sigwait/sigtimedwait.
1570 for (int si
= ACE_SIGRTMIN
; si
<= ACE_SIGRTMAX
; si
++)
1572 member
= sigismember (&signal_set
,
1575 ACELIB_ERROR ((LM_ERROR
,
1576 ACE_TEXT("%N:%l:(%P | %t)::%p\n"),
1577 ACE_TEXT("ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor:")
1578 ACE_TEXT("sigismember failed")));
1579 else if (member
== 1)
1581 sigaddset (&this->RT_completion_signals_
, si
);
1582 this->setup_signal_handler (si
);
1586 // Mask all the signals.
1587 this->block_signals ();
1589 // we do not have to create notify manager
1590 // but we should start pseudo-asynchronous accept task
1591 // one per all future acceptors
1593 this->get_asynch_pseudo_task().start ();
1597 ACE_POSIX_SIG_Proactor::~ACE_POSIX_SIG_Proactor ()
1601 // @@ Enable the masked signals again.
1604 ACE_POSIX_Proactor::Proactor_Type
1605 ACE_POSIX_SIG_Proactor::get_impl_type ()
1607 return PROACTOR_SIG
;
1611 ACE_POSIX_SIG_Proactor::handle_events (ACE_Time_Value
&wait_time
)
1613 // Decrement <wait_time> with the amount of time spent in the method
1614 ACE_Countdown_Time
countdown (&wait_time
);
1615 return this->handle_events_i (&wait_time
);
1619 ACE_POSIX_SIG_Proactor::handle_events ()
1621 return this->handle_events_i (0);
1625 ACE_POSIX_SIG_Proactor::notify_completion (int sig_num
)
1627 // Get this process id.
1628 pid_t
const pid
= ACE_OS::getpid ();
1629 if (pid
== (pid_t
) -1)
1630 ACELIB_ERROR_RETURN ((LM_ERROR
,
1631 ACE_TEXT("Error:%N:%l(%P | %t):%p"),
1632 ACE_TEXT("<getpid> failed")),
1635 // Set the signal information.
1637 #if defined (ACE_HAS_SIGVAL_SIGVAL_INT)
1638 value
.sigval_int
= -1;
1640 value
.sival_int
= -1;
1641 #endif /* ACE_HAS_SIGVAL_SIGVAL_INT */
1643 // Queue the signal.
1644 if (sigqueue (pid
, sig_num
, value
) == 0)
1647 if (errno
!= EAGAIN
)
1648 ACELIB_ERROR_RETURN ((LM_ERROR
,
1649 ACE_TEXT("Error:%N:%l:(%P | %t):%p\n"),
1650 ACE_TEXT("<sigqueue> failed")),
1655 ACE_Asynch_Result_Impl
*
1656 ACE_POSIX_SIG_Proactor::create_asynch_timer
1657 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
1659 const ACE_Time_Value
&tv
,
1666 // Fix the signal number.
1667 if (signal_number
== -1)
1670 for (si
= ACE_SIGRTMAX
;
1671 (is_member
== 0) && (si
>= ACE_SIGRTMIN
);
1674 is_member
= sigismember (&this->RT_completion_signals_
,
1676 if (is_member
== -1)
1677 ACELIB_ERROR_RETURN ((LM_ERROR
,
1678 "%N:%l:(%P | %t)::%s\n",
1679 "ACE_POSIX_SIG_Proactor::create_asynch_timer:"
1680 "sigismember failed"),
1685 ACELIB_ERROR_RETURN ((LM_ERROR
,
1686 "Error:%N:%l:(%P | %t)::%s\n",
1687 "ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor:"
1688 "Signal mask set empty"),
1691 // + 1 to nullify loop increment.
1692 signal_number
= si
+ 1;
1695 ACE_Asynch_Result_Impl
*implementation
;
1696 ACE_NEW_RETURN (implementation
,
1697 ACE_POSIX_Asynch_Timer (handler_proxy
,
1704 return implementation
;
1709 sig_handler (int sig_num
, siginfo_t
*, ucontext_t
*)
1711 // Should never be called
1712 ACELIB_DEBUG ((LM_DEBUG
,
1713 "%N:%l:(%P | %t)::sig_handler received signal: %d\n",
1719 ACE_POSIX_SIG_Proactor::setup_signal_handler (int signal_number
) const
1721 // Set up the specified signal so that signal information will be
1722 // passed to sigwaitinfo/sigtimedwait. Don't change the default
1723 // signal handler - having a handler and waiting for the signal can
1724 // produce undefined behavior.
1726 // But can not use SIG_DFL
1727 // With SIG_DFL after delivering the first signal
1728 // SIG_DFL handler resets SA_SIGINFO flags
1729 // and we will lose all information sig_info
1730 // At least all SunOS have such behavior
1732 struct sigaction reaction
;
1733 sigemptyset (&reaction
.sa_mask
); // Nothing else to mask.
1734 reaction
.sa_flags
= SA_SIGINFO
; // Realtime flag.
1735 reaction
.sa_sigaction
= ACE_SIGNAL_C_FUNC (sig_handler
); // (SIG_DFL);
1736 int sigaction_return
= ACE_OS::sigaction (signal_number
,
1739 if (sigaction_return
== -1)
1740 ACELIB_ERROR_RETURN ((LM_ERROR
,
1741 ACE_TEXT("Error:%p\n"),
1742 ACE_TEXT("Proactor couldnt do sigaction for the RT SIGNAL")),
1745 ACE_UNUSED_ARG(signal_number
);
1752 ACE_POSIX_SIG_Proactor::block_signals () const
1754 return ACE_OS::pthread_sigmask (SIG_BLOCK
, &this->RT_completion_signals_
, 0);
1758 ACE_POSIX_SIG_Proactor::allocate_aio_slot (ACE_POSIX_Asynch_Result
*result
)
1762 //try to find free slot as usual, starting from 0
1763 for (i
= 0; i
< this->aiocb_list_max_size_
; i
++)
1764 if (result_list_
[i
] == 0)
1767 if (i
>= this->aiocb_list_max_size_
)
1768 ACELIB_ERROR_RETURN ((LM_ERROR
,
1769 "%N:%l:(%P | %t)::\n"
1770 "ACE_POSIX_SIG_Proactor::allocate_aio_slot "
1771 "internal Proactor error 1\n"),
1774 // setup OS notification methods for this aio
1775 // store index!!, not pointer in signal info
1776 result
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
1777 result
->aio_sigevent
.sigev_signo
= result
->signal_number ();
1778 #if defined (ACE_HAS_SIGVAL_SIGVAL_INT)
1779 result
->aio_sigevent
.sigev_value
.sigval_int
= static_cast<int> (i
);
1781 result
->aio_sigevent
.sigev_value
.sival_int
= static_cast<int> (i
);
1782 #endif /* ACE_HAS_SIGVAL_SIGVAL_INT */
1784 return static_cast<ssize_t
> (i
);
1788 ACE_POSIX_SIG_Proactor::handle_events_i (const ACE_Time_Value
*timeout
)
1790 int result_sigwait
= 0;
1795 // Wait for the signals.
1798 result_sigwait
= ACE_OS::sigwaitinfo (&this->RT_completion_signals_
,
1803 result_sigwait
= ACE_OS::sigtimedwait (&this->RT_completion_signals_
,
1806 if (result_sigwait
== -1 && errno
== EAGAIN
)
1810 while (result_sigwait
== -1 && errno
== EINTR
);
1812 if (result_sigwait
== -1) // Not a timeout, not EINTR: tell caller of error
1815 // Decide what to do. We always check the completion queue since it's an
1816 // easy, quick check. What is decided here is whether to check for
1817 // I/O completions and, if so, how completely to scan.
1818 int flg_aio
= 0; // 1 if AIO Completion possible
1820 size_t index
= 0; // start index to scan aiocb list
1821 size_t count
= 1; // max number of aiocbs to scan
1822 int error_status
= 0;
1823 size_t transfer_count
= 0;
1825 if (sig_info
.si_code
== SI_ASYNCIO
)
1827 flg_aio
= 1; // AIO signal received
1828 // define index to start
1829 // nothing will happen if it contains garbage
1830 #if defined (ACE_HAS_SIGVAL_SIGVAL_INT)
1831 index
= static_cast<size_t> (sig_info
.si_value
.sigval_int
);
1833 index
= static_cast<size_t> (sig_info
.si_value
.sival_int
);
1834 #endif /* ACE_HAS_SIGVAL_SIGVAL_INT */
1836 else if (sig_info
.si_code
!= SI_QUEUE
)
1838 // Unknown signal code.
1839 // may some other third-party libraries could send it
1840 // or message queue could also generate it !
1841 // So print the message and check our completions
1842 ACELIB_ERROR ((LM_DEBUG
,
1843 ACE_TEXT ("%N:%l:(%P | %t): ")
1844 ACE_TEXT ("ACE_POSIX_SIG_Proactor::handle_events: ")
1845 ACE_TEXT ("Unexpected signal code (%d) returned ")
1846 ACE_TEXT ("from sigwait; expecting %d\n"),
1847 result_sigwait
, sig_info
.si_code
));
1857 ACE_POSIX_Asynch_Result
*asynch_result
=
1858 find_completed_aio (error_status
,
1863 if (asynch_result
== 0)
1866 // Call the application code.
1867 this->application_specific_code (asynch_result
,
1869 0, // No completion key.
1870 error_status
); // Error
1873 // process post_completed results
1874 ret_que
= this->process_result_queue ();
1876 // Uncomment this if you want to test
1877 // and research the behavior of you system
1879 ACELIB_DEBUG ((LM_DEBUG
,
1880 "(%t) NumAIO=%d NumQueue=%d\n",
1884 return ret_aio
+ ret_que
> 0 ? 1 : 0;
1887 #endif /* ACE_HAS_POSIX_REALTIME_SIGNALS */
1889 // *********************************************************************
1891 ACE_POSIX_Asynch_Timer::ACE_POSIX_Asynch_Timer
1892 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
1894 const ACE_Time_Value
&tv
,
1898 : ACE_POSIX_Asynch_Result
1899 (handler_proxy
, act
, event
, 0, 0, priority
, signal_number
),
1905 ACE_POSIX_Asynch_Timer::complete (size_t /* bytes_transferred */,
1907 const void * /* completion_key */,
1910 ACE_Handler
*handler
= this->handler_proxy_
.get ()->handler ();
1912 handler
->handle_time_out (this->time_
, this->act ());
1916 // *********************************************************************
1918 ACE_POSIX_Wakeup_Completion::ACE_POSIX_Wakeup_Completion
1919 (const ACE_Handler::Proxy_Ptr
&handler_proxy
,
1924 : ACE_Asynch_Result_Impl (),
1925 ACE_POSIX_Asynch_Result (handler_proxy
,
1935 ACE_POSIX_Wakeup_Completion::~ACE_POSIX_Wakeup_Completion ()
1940 ACE_POSIX_Wakeup_Completion::complete (size_t /* bytes_transferred */,
1942 const void * /* completion_key */,
1945 ACE_Handler
*handler
= this->handler_proxy_
.get ()->handler ();
1947 handler
->handle_wakeup ();
1950 ACE_END_VERSIONED_NAMESPACE_DECL
1952 #endif /* ACE_HAS_AIO_CALLS */