2 //=============================================================================
4 * @file test_proactor3.cpp
6 * This program illustrates how the <ACE_Proactor> can be used to
7 * implement an application that does various asynchronous
10 * @author Irfan Pyarali <irfan@cs.wustl.edu> modified by Alexander Libman <alibman@baltimore.com> from original test_proactor.cpp
12 //=============================================================================
15 #include "ace/Signal.h"
17 #include "ace/Service_Config.h"
18 #include "ace/Proactor.h"
19 #include "ace/Asynch_IO.h"
20 #include "ace/Asynch_IO_Impl.h"
21 #include "ace/Asynch_Acceptor.h"
22 #include "ace/INET_Addr.h"
23 #include "ace/Manual_Event.h"
24 #include "ace/SOCK_Connector.h"
25 #include "ace/SOCK_Acceptor.h"
26 #include "ace/SOCK_Stream.h"
27 #include "ace/Message_Block.h"
28 #include "ace/Get_Opt.h"
30 // FUZZ: disable check_for_streams_include
31 #include "ace/streams.h"
36 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
37 // This only works on Win32 platforms and on Unix platforms
38 // supporting POSIX aio calls.
40 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
42 #include "ace/WIN32_Proactor.h"
44 #elif defined (ACE_HAS_AIO_CALLS)
46 #include "ace/POSIX_Proactor.h"
48 #endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
50 // Some debug helper functions
51 static int disable_signal (int sigmin
, int sigmax
);
53 static int print_sigmask ();
56 #define COUT(X) cout << X; cout.flush ();
58 // Proactor Type (UNIX only, Win32 ignored) 0-default, 1 -AIOCB,
60 static int proactor_type
= 0;
62 // POSIX : > 0 max number aio operations proactor,
63 static int max_aio_operations
= 0;
65 // Host that we're connecting to.
66 static ACE_TCHAR
*host
= 0;
68 // number of Senders instances
69 static int senders
= 1;
70 static const int MaxSenders
= 100;
72 // duplex mode: ==0 half-duplex
74 static int duplex
= 0;
76 // number threads in the Proactor thread pool
77 static int threads
= 1;
79 // Port that we're receiving connections on.
80 static u_short port
= ACE_DEFAULT_SERVER_PORT
;
85 * @brief MyTask plays role for Proactor threads pool
87 class MyTask
: public ACE_Task
<ACE_MT_SYNCH
>
90 MyTask () : threads_ (0), proactor_ (0) {}
93 void waitready () { event_
.wait (); }
96 ACE_Recursive_Thread_Mutex mutex_
;
98 ACE_Proactor
*proactor_
;
99 ACE_Manual_Event event_
;
101 void create_proactor ();
102 void delete_proactor ();
106 MyTask::create_proactor ()
108 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
112 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
113 ACE_WIN32_Proactor
*proactor
= new ACE_WIN32_Proactor
;
114 ACE_DEBUG ((LM_DEBUG
,"(%t) Create Proactor Type=WIN32"));
116 #elif defined (ACE_HAS_AIO_CALLS)
118 ACE_POSIX_Proactor
*proactor
= 0;
120 switch (proactor_type
)
123 proactor
= new ACE_POSIX_AIOCB_Proactor (max_aio_operations
);
124 ACE_DEBUG ((LM_DEBUG
,"(%t) Create Proactor Type=AIOCB\n"));
127 proactor
= new ACE_POSIX_SIG_Proactor
;
128 ACE_DEBUG ((LM_DEBUG
,"(%t) Create Proactor Type=SIG\n"));
131 proactor
= new ACE_POSIX_SIG_Proactor
;
132 ACE_DEBUG ((LM_DEBUG
,"(%t) Create Proactor Type=SIG\n"));
137 proactor_
= new ACE_Proactor (proactor
, 1);
139 ACE_Proactor::instance(proactor_
);
147 MyTask::delete_proactor ()
149 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
152 ACE_DEBUG ((LM_DEBUG
, "(%t) Delete Proactor\n"));
153 ACE_Proactor::instance ((ACE_Proactor
*) 0);
162 ACE_DEBUG ((LM_DEBUG
, "(%t) MyTask started\n"));
165 disable_signal (ACE_SIGRTMIN
, ACE_SIGRTMAX
);
167 while (ACE_Proactor::event_loop_done () == 0)
168 ACE_Proactor::run_event_loop ();
172 ACE_DEBUG ((LM_DEBUG
, "(%t) MyTask finished\n"));
176 class Receiver
: public ACE_Service_Handler
182 //FUZZ: disable check_for_lack_ACE_OS
183 /// This is called after the new connection has been accepted.
184 ///FUZZ: enable check_for_lack_ACE_OS
185 virtual void open (ACE_HANDLE handle
,
186 ACE_Message_Block
&message_block
);
188 static long get_number_sessions () { return sessions_
; }
191 // These methods are called by the framework
193 /// This is called when asynchronous <read> operation from the socket
195 virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result
&result
);
197 /// This is called when an asynchronous <write> to the file
199 virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result
&result
);
202 int initiate_read_stream ();
203 int initiate_write_stream (ACE_Message_Block
& mb
, int nBytes
);
204 int check_destroy ();
206 ACE_Asynch_Read_Stream rs_
;
207 ACE_Asynch_Write_Stream ws_
;
209 ACE_Recursive_Thread_Mutex mutex_
;
211 static long sessions_
;
214 long Receiver::sessions_
= 0;
216 Receiver::Receiver ()
217 : handle_ (ACE_INVALID_HANDLE
),
220 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
222 ACE_DEBUG ((LM_DEBUG
, "Receiver Ctor sessions_=%d\n", sessions_
));
225 Receiver::~Receiver ()
227 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
229 ACE_OS::closesocket (this->handle_
);
230 ACE_DEBUG ((LM_DEBUG
, "~Receiver Dtor sessions_=%d\n", sessions_
));
233 // return true if we alive, false we commited suicide
235 Receiver::check_destroy ()
238 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, locker
, mutex_
, -1);
249 Receiver::open (ACE_HANDLE handle
,
252 ACE_DEBUG ((LM_DEBUG
,
253 "%N:%l:Receiver::open called\n"));
255 this->handle_
= handle
;
257 if (this->ws_
.open (*this, this->handle_
) == -1)
258 ACE_ERROR ((LM_ERROR
,
260 "ACE_Asynch_Write_Stream::open"));
261 else if (this->rs_
.open (*this, this->handle_
) == -1)
262 ACE_ERROR ((LM_ERROR
,
264 "ACE_Asynch_Read_Stream::open"));
266 initiate_read_stream ();
272 Receiver::initiate_read_stream ()
274 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, locker
, mutex_
, -1);
276 ACE_Message_Block
*mb
= 0;
278 ACE_Message_Block (BUFSIZ
+ 1),
282 if (this->rs_
.read (*mb
, mb
->size ()- 1) == -1)
285 ACE_ERROR_RETURN ((LM_ERROR
,
287 "ACE_Asynch_Read_Stream::read"),
296 Receiver::initiate_write_stream (ACE_Message_Block
&mb
, int nbytes
)
298 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, locker
, mutex_
, -1);
302 ACE_ERROR_RETURN((LM_ERROR
,
303 "ACE_Asynch_Write_Stream::write nbytes <0 "),
307 if (this->ws_
.write (mb
, nbytes
) == -1)
310 ACE_ERROR_RETURN((LM_ERROR
,
312 "ACE_Asynch_Write_Stream::write"),
321 Receiver::handle_read_stream (const ACE_Asynch_Read_Stream::Result
&result
)
324 result
.message_block ().rd_ptr ()[result
.bytes_transferred ()] = '\0';
326 if (result
.bytes_transferred () == 0 || result
.error () != 0)
328 ACE_DEBUG ((LM_DEBUG
, "handle_read_stream called\n"));
329 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
330 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_to_read", result
.bytes_to_read ()));
331 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "handle", result
.handle ()));
332 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_transfered", result
.bytes_transferred ()));
333 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "act", (u_long
) result
.act ()));
334 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "success", result
.success ()));
335 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "completion_key", (u_long
) result
.completion_key ()));
336 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "error", result
.error ()));
337 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
338 ACE_DEBUG ((LM_DEBUG
, "%s = %s\n", "message_block", result
.message_block ().rd_ptr ()));
341 if (result
.success () && result
.bytes_transferred () != 0)
343 // Successful read: write the data to the file asynchronously.
344 // Note how we reuse the <ACE_Message_Block> for the writing.
345 // Therefore, we do not delete this buffer because it is handled
346 // in <handle_write_stream>.
348 if(this->initiate_write_stream (result
.message_block (),
349 result
.bytes_transferred ()) == 0)
353 // Initiate new read from the stream.
354 this->initiate_read_stream ();
360 result
.message_block ().release ();
361 ACE_DEBUG ((LM_DEBUG
, "Receiver completed\n"));
365 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
372 Receiver::handle_write_stream (const ACE_Asynch_Write_Stream::Result
&result
)
374 if (result
.bytes_transferred () == 0 || result
.error () != 0)
376 ACE_DEBUG ((LM_DEBUG
, "handle_write_stream called\n"));
378 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
379 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_to_write", result
.bytes_to_write ()));
380 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "handle", result
.handle ()));
381 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_transfered", result
.bytes_transferred ()));
382 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "act", (u_long
) result
.act ()));
383 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "success", result
.success ()));
384 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "completion_key", (u_long
) result
.completion_key ()));
385 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "error", result
.error ()));
386 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
389 result
.message_block ().release ();
391 if (result
.success () && result
.bytes_transferred () != 0)
393 // This code is not robust enough to deal with short file writes
394 // (which hardly ever happen);-)
395 // ACE_ASSERT (result.bytes_to_write () == result.bytes_transferred ());
398 initiate_read_stream ();
402 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
411 * @brief Sends welcome messages receives them back.
413 class Sender
: public ACE_Handler
419 //FUZZ: disable check_for_lack_ACE_OS
420 ///FUZZ: enable check_for_lack_ACE_OS
421 int open (const ACE_TCHAR
*host
, u_short port
);
424 ACE_HANDLE
handle () const;
425 virtual void handle (ACE_HANDLE
);
428 // These methods are called by the freamwork
430 /// This is called when asynchronous reads from the socket complete
431 virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result
&result
);
433 /// This is called when asynchronous writes from the socket complete
434 virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result
&result
);
437 int initiate_read_stream ();
438 int initiate_write_stream ();
440 /// Network I/O handle
441 ACE_SOCK_Stream stream_
;
443 /// ws (write stream): for writing to the socket
444 ACE_Asynch_Write_Stream ws_
;
446 /// rs (read file): for reading from the socket
447 ACE_Asynch_Read_Stream rs_
;
450 ACE_Message_Block welcome_message_
;
452 ACE_Recursive_Thread_Mutex mutex_
;
456 static const char *data
= "Welcome to Irfan World! Irfan RULES here !!\n";
461 // Moment of inspiration... :-)
462 this->welcome_message_
.init (data
, ACE_OS::strlen (data
));
470 void Sender::close ()
472 this->stream_
.close ();
475 ACE_HANDLE
Sender::handle () const
477 return this->stream_
.get_handle ();
480 void Sender::handle (ACE_HANDLE handle
)
482 this->stream_
.set_handle (handle
);
485 int Sender::open (const ACE_TCHAR
*host
, u_short port
)
488 // Connect to remote host
489 ACE_INET_Addr
address (port
, host
);
490 ACE_SOCK_Connector connector
;
492 if (connector
.connect (this->stream_
, address
) == -1)
494 ACE_ERROR_RETURN ((LM_ERROR
,
496 "ACE_SOCK_Connector::connect"),
500 // Open ACE_Asynch_Write_Stream
501 if (this->ws_
.open (*this) == -1)
502 ACE_ERROR_RETURN ((LM_ERROR
,
504 "ACE_Asynch_Write_Stream::open"),
507 // Open ACE_Asynch_Read_Stream
508 if (this->rs_
.open (*this) == -1)
509 ACE_ERROR_RETURN ((LM_ERROR
,
511 "ACE_Asynch_Read_Stream::open"),
514 // Start an asynchronous transmit file
515 if (this->initiate_write_stream () == -1)
519 // Start an asynchronous read file
520 if (this->initiate_read_stream () == -1)
527 Sender::initiate_write_stream ()
529 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, locker
, mutex_
, -1);
531 welcome_message_
.rd_ptr(welcome_message_
.base ());
532 welcome_message_
.wr_ptr(welcome_message_
.base ());
533 welcome_message_
.wr_ptr (ACE_OS::strlen (data
));
535 if (this->ws_
.write (welcome_message_
,
536 welcome_message_
.length ()) == -1)
537 ACE_ERROR_RETURN((LM_ERROR
,
539 "ACE_Asynch_Write_Stream::write"),
546 Sender::initiate_read_stream ()
548 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, locker
, mutex_
, -1);
550 // Create a new <Message_Block>. Note that this message block will
551 // be used both to <read> data asynchronously from the socket and to
552 // <write> data asynchronously to the file.
553 ACE_DEBUG ((LM_DEBUG
,
554 "initiate_read_stream called\n"));
556 ACE_Message_Block
*mb
= 0;
558 ACE_Message_Block (BUFSIZ
+ 1),
562 if (this->rs_
.read (*mb
, mb
->size ()- 1) == -1)
565 ACE_ERROR_RETURN ((LM_ERROR
,
567 "ACE_Asynch_Read_Stream::read"),
576 Sender::handle_write_stream (const ACE_Asynch_Write_Stream::Result
&result
)
578 if (result
.bytes_transferred () == 0 || result
.error () != 0)
580 ACE_DEBUG ((LM_DEBUG
, "handle_write_stream called\n"));
583 result
.message_block ().rd_ptr (result
.message_block ().rd_ptr () - result
.bytes_transferred ());
585 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
586 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_to_write", result
.bytes_to_write ()));
587 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "handle", result
.handle ()));
588 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_transfered", result
.bytes_transferred ()));
589 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "act", (u_long
) result
.act ()));
590 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "success", result
.success ()));
591 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "completion_key", (u_long
) result
.completion_key ()));
592 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "error", result
.error ()));
593 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
594 ACE_DEBUG ((LM_DEBUG
, "%s = %s\n", "message_block", result
.message_block ().rd_ptr ()));
597 // Simplify just for Test
598 if (result
.success () && result
.bytes_transferred () != 0)
600 if (duplex
!= 0) // full duplex, continue write
601 initiate_write_stream ();
602 else // half-duplex read reply, after read we will start write
603 initiate_read_stream ();
607 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
613 Sender::handle_read_stream (const ACE_Asynch_Read_Stream::Result
&result
)
615 if (result
.bytes_transferred () == 0 || result
.error () != 0)
617 ACE_DEBUG ((LM_DEBUG
,
618 "handle_read_stream called\n"));
621 result
.message_block ().rd_ptr ()[result
.bytes_transferred ()] = '\0';
623 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
624 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_to_read", result
.bytes_to_read ()));
625 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "handle", result
.handle ()));
626 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "bytes_transfered", result
.bytes_transferred ()));
627 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "act", (u_long
) result
.act ()));
628 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "success", result
.success ()));
629 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "completion_key", (u_long
) result
.completion_key ()));
630 ACE_DEBUG ((LM_DEBUG
, "%s = %d\n", "error", result
.error ()));
631 ACE_DEBUG ((LM_DEBUG
, "********************\n"));
632 ACE_DEBUG ((LM_DEBUG
, "%s = %s\n", "message_block", result
.message_block ().rd_ptr ()));
635 result
.message_block().release ();
637 if (result
.success () && result
.bytes_transferred () != 0)
639 // Successful read: write the data to the file asynchronously.
640 // Note how we reuse the <ACE_Message_Block> for the writing.
641 // Therefore, we do not delete this buffer because it is handled
642 // in <handle_write_stream>.
644 if (duplex
!= 0) // full duplex, continue read
645 initiate_read_stream ();
646 else // half-duplex writey, after write we will start read
647 initiate_write_stream ();
651 ACE_GUARD (ACE_Recursive_Thread_Mutex
, locker
, mutex_
);
657 set_proactor_type (const char *ptype
)
662 switch (ACE_OS::ace_toupper (*ptype
))
664 case 'D' : proactor_type
= 0; return true;
665 case 'A' : proactor_type
= 1; return true;
666 case 'I' : proactor_type
= 2; return true;
672 parse_args (int argc
, ACE_TCHAR
*argv
[])
674 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT("t:o:n:p:d:h:s:u"));
677 while ((c
= get_opt ()) != EOF
)
681 duplex
= ACE_OS::atoi (get_opt
.opt_arg ());
683 case 'h': // host for sender
684 host
= get_opt
.opt_arg ();
686 case 'p': // port number
687 port
= ACE_OS::atoi (get_opt
.opt_arg ());
689 case 'n': // thread pool size
690 threads
= ACE_OS::atoi (get_opt
.opt_arg ());
692 case 's': // number of senders
693 senders
= ACE_OS::atoi (get_opt
.opt_arg ());
694 if (senders
> MaxSenders
)
695 senders
= MaxSenders
;
697 case 'o': // max number of aio for proactor
698 max_aio_operations
= ACE_OS::atoi (get_opt
.opt_arg ());
700 case 't': // Proactor Type
701 if (set_proactor_type (get_opt
.opt_arg ()))
705 ACE_ERROR ((LM_ERROR
, "%p.",
707 "\n-o <max number of started aio operations for Proactor>"
708 "\n-t <Proactor type> UNIX-only, Win32-default always:"
713 "\n-d <duplex mode 1-on/0-off>"
714 "\n-h <host> for Sender mode"
715 "\n-n <number threads for Proactor pool>"
716 "\n-p <port to listen/connect>"
717 "\n-s <number of sender's instances>"
718 "\n-u show this message"
728 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
730 if (parse_args (argc
, argv
) == -1)
733 disable_signal (ACE_SIGRTMIN
, ACE_SIGRTMAX
);
737 if (task1
.activate (THR_NEW_LWP
, threads
) == -1)
738 ACE_ERROR_RETURN ((LM_ERROR
,
743 // wait for creation of Proactor
746 Sender
* send_list
[MaxSenders
];
748 ACE_Asynch_Acceptor
<Receiver
> acceptor
;
754 if (host
== 0) // Acceptor
756 // Simplify, initial read with zero size
757 if (acceptor
.open (ACE_INET_Addr (port
),0,1) == 0)
762 for (i
= 0; i
< senders
; ++i
)
763 send_list
[i
] = new Sender
;
765 for (i
= 0; i
< senders
; ++i
)
766 if (send_list
[i
]->open (host
, port
) == 0)
772 cout
<< "Press any key to stop=>" << flush
;
777 ACE_Proactor::end_event_loop ();
779 if (host
!= 0) // we are sender
781 for (i
= 0; i
< senders
; ++i
)
782 send_list
[i
]->close ();
786 ACE_Thread_Manager
*tm
=
787 ACE_Thread_Manager::instance();
789 tm
->wait_task (&task1
);
791 cout
<< "\nNumber of Receivers objects="
792 << Receiver::get_number_sessions ()
795 for (i
= 0; i
< senders
; ++i
)
797 delete (send_list
[i
]);
805 disable_signal (int sigmin
, int sigmax
)
810 if (ACE_OS::sigemptyset (&signal_set
) == - 1)
811 ACE_ERROR ((LM_ERROR
,
812 "Error:(%P | %t):%p\n",
813 "sigemptyset failed"));
815 for (int i
= sigmin
; i
<= sigmax
; i
++)
816 ACE_OS::sigaddset (&signal_set
, i
);
818 // Put the <signal_set>.
819 if (ACE_OS::pthread_sigmask (SIG_BLOCK
, &signal_set
, 0) != 0)
820 ACE_ERROR ((LM_ERROR
,
821 "Error:(%P | %t):%p\n",
822 "pthread_sigmask failed"));
824 ACE_UNUSED_ARG (sigmin
);
825 ACE_UNUSED_ARG (sigmax
);
826 #endif /* ACE_WIN32 */
831 // Get the <signal_set> back from the OS.
841 COUT ("\n=============Signal Mask==========")
843 if (ACE_OS::pthread_sigmask (SIG_SETMASK
, 0, & mask
) != 0)
844 ACE_ERROR ((LM_ERROR
,
845 "Error:(%P | %t):%p\n",
846 "ACE_OS::pthread_sigmask failed"));
848 for (int i
= 1; i
< 1000; i
++)
850 member
= ACE_OS::sigismember (&mask
,i
);
861 #endif /* ACE_WIN32 */
866 #else /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */
869 ACE_TMAIN (int, ACE_TCHAR
*[])
871 ACE_DEBUG ((LM_DEBUG
,
872 "This example does not work on this platform.\n"));
876 #endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_AIO_CALLS */