summaryrefslogtreecommitdiff
path: root/examples/Reactor
diff options
context:
space:
mode:
Diffstat (limited to 'examples/Reactor')
-rw-r--r--examples/Reactor/Dgram/CODgram.cpp121
-rw-r--r--examples/Reactor/Dgram/Dgram.cpp121
-rw-r--r--examples/Reactor/Dgram/Makefile135
-rw-r--r--examples/Reactor/Makefile24
-rw-r--r--examples/Reactor/Misc/Makefile378
-rw-r--r--examples/Reactor/Misc/notification.cpp249
-rw-r--r--examples/Reactor/Misc/pingpong.cpp241
-rw-r--r--examples/Reactor/Misc/signal_tester.cpp221
-rw-r--r--examples/Reactor/Misc/test_event_handler_t.cpp45
-rw-r--r--examples/Reactor/Misc/test_handle_set.cpp75
-rw-r--r--examples/Reactor/Misc/test_reactors.cpp205
-rw-r--r--examples/Reactor/Misc/test_signals.cpp226
-rw-r--r--examples/Reactor/Misc/test_time_value.cpp69
-rw-r--r--examples/Reactor/Misc/test_timer_queue.cpp47
-rw-r--r--examples/Reactor/Multicast/Log_Wrapper.cpp75
-rw-r--r--examples/Reactor/Multicast/Log_Wrapper.h59
-rw-r--r--examples/Reactor/Multicast/Makefile69
-rw-r--r--examples/Reactor/Multicast/README15
-rw-r--r--examples/Reactor/Multicast/client.cpp110
-rw-r--r--examples/Reactor/Multicast/server.cpp157
-rw-r--r--examples/Reactor/Ntalker/Makefile91
-rw-r--r--examples/Reactor/Ntalker/ntalker.cpp188
-rw-r--r--examples/Reactor/README20
-rw-r--r--examples/Reactor/ReactorEx/README204
-rw-r--r--examples/Reactor/ReactorEx/reactorex.mak535
-rw-r--r--examples/Reactor/ReactorEx/reactorex.mdpbin0 -> 51200 bytes
-rw-r--r--examples/Reactor/ReactorEx/test_reactorEx.cpp444
-rw-r--r--examples/Reactor/ReactorEx/test_remove_handler.cpp94
-rw-r--r--examples/Reactor/WFMO_Reactor/README204
-rw-r--r--examples/Reactor/WFMO_Reactor/reactorex.mak535
-rw-r--r--examples/Reactor/WFMO_Reactor/reactorex.mdpbin0 -> 51200 bytes
-rw-r--r--examples/Reactor/WFMO_Reactor/test_reactorEx.cpp444
-rw-r--r--examples/Reactor/WFMO_Reactor/test_remove_handler.cpp94
33 files changed, 5495 insertions, 0 deletions
diff --git a/examples/Reactor/Dgram/CODgram.cpp b/examples/Reactor/Dgram/CODgram.cpp
new file mode 100644
index 00000000000..8856e92d3c5
--- /dev/null
+++ b/examples/Reactor/Dgram/CODgram.cpp
@@ -0,0 +1,121 @@
+/* Exercise the ACE_SOCK_CODgram wrapper along with the ACE_Reactor.
+// @(#)CODgram.cpp 1.1 10/18/96
+
+
+ Typical invocation sequence is:
+
+ % CODgram 10000 localhost 10001 &
+ % CODgram 10001 localhost 10000
+
+ This will start two interacting copies of the CODgram
+ application. */
+
+#include "ace/Reactor.h"
+#include "ace/SOCK_CODgram.h"
+#include "ace/INET_Addr.h"
+
+class AAL_CP : public ACE_Event_Handler, public ACE_SOCK_CODgram
+{
+public:
+ AAL_CP (const ACE_INET_Addr &remote_addr,
+ const ACE_INET_Addr &local_addr);
+
+ virtual int get_handle () const;
+
+ virtual int handle_input (int fd);
+
+ virtual int handle_timeout (const ACE_Time_Value & tv,
+ const void *arg = 0);
+};
+
+AAL_CP::AAL_CP (const ACE_INET_Addr &remote_addr,
+ const ACE_INET_Addr &local_addr)
+ : ACE_SOCK_CODgram (remote_addr, local_addr)
+{
+}
+
+int
+AAL_CP::get_handle () const
+{
+ return ACE_SOCK_CODgram::get_handle ();
+}
+
+int
+AAL_CP::handle_input (int)
+{
+ char buf[128];
+ int n;
+ ACE_DEBUG ((LM_DEBUG, "Activity occurred on handle %d!\n",
+ ACE_SOCK_CODgram::get_handle ()));
+ if ((n = ACE_SOCK_CODgram::recv (buf, sizeof buf)) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "got buf = %s\n", buf));
+
+ return 0;
+}
+
+int
+AAL_CP::handle_timeout (const ACE_Time_Value &, const void *)
+{
+ ACE_DEBUG ((LM_DEBUG, "timed out for aa1\n"));
+ return 0;
+}
+
+main(int argc, char *argv[])
+{
+ /* Estabish call backs, and socket names */
+ if (argc != 4)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s localport remotehost remoteport\n",
+ argv[0]), -1);
+
+ ACE_Reactor reactor;
+ char buf[128];
+ u_short localport = ACE_OS::atoi (argv[1]);
+ u_short remoteport = ACE_OS::atoi (argv[3]);
+ char *remotehost = argv[2];
+
+ ACE_INET_Addr remote_addr (remoteport, remotehost);
+ ACE_INET_Addr local_addr (localport);
+
+ AAL_CP aal (remote_addr, local_addr);
+
+ if (localport == 10000) // HACK
+ {
+ ACE_OS::memcpy (buf, "Data to transmit", sizeof buf);
+ ACE_DEBUG ((LM_DEBUG, "sending data\n"));
+
+ for (int i = 0; i < 20; i++)
+ {
+ aal.send (buf, sizeof buf);
+ ACE_DEBUG ((LM_DEBUG, ".\n"));
+ ACE_OS::sleep (1);
+ }
+ }
+
+ /* read data from other side */
+ if (reactor.register_handler (&aal, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE_Reactor::register_handler"), -1);
+
+ if (reactor.schedule_timer (&aal, 0,
+ ACE_Time_Value (1, 0),
+ ACE_Time_Value (0, 3500000)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE_Reactor::schedule_timer"), -1);
+
+ ACE_OS::memcpy (buf, "Data to transmit", sizeof buf);
+
+ for (;;)
+ {
+ /* Wait at most two seconds */
+ ACE_Time_Value tv (2, 0);
+
+ reactor.handle_events (tv);
+
+ ACE_DEBUG ((LM_DEBUG, "return from handle events\n"));
+ aal.send (buf, sizeof buf);
+ ACE_DEBUG ((LM_DEBUG, ".\n"));
+ }
+
+ return 0;
+}
diff --git a/examples/Reactor/Dgram/Dgram.cpp b/examples/Reactor/Dgram/Dgram.cpp
new file mode 100644
index 00000000000..d2f4305f267
--- /dev/null
+++ b/examples/Reactor/Dgram/Dgram.cpp
@@ -0,0 +1,121 @@
+// Exercise the ACE_SOCK_Dgram wrapper along with the ACE_Reactor.
+// @(#)Dgram.cpp 1.1 10/18/96
+
+// Typical invocation sequence is:
+//
+// % Dgram 10000 localhost 10001 &
+// % Dgram 10001 localhost 10000
+//
+// This will start two interacting copies of the Dgram
+// application.
+
+#include "ace/Reactor.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+
+class AAL_CP : public ACE_Event_Handler, public ACE_SOCK_Dgram
+{
+public:
+ AAL_CP (const ACE_INET_Addr &local_addr);
+
+ virtual ACE_HANDLE get_handle (void) const;
+
+ virtual int handle_input (ACE_HANDLE handle);
+
+ virtual int handle_timeout (const ACE_Time_Value & tv,
+ const void *arg = 0);
+};
+
+AAL_CP::AAL_CP (const ACE_INET_Addr &local_addr)
+ : ACE_SOCK_Dgram (local_addr)
+{
+}
+
+ACE_HANDLE
+AAL_CP::get_handle (void) const
+{
+ return ACE_SOCK_Dgram::get_handle ();
+}
+
+int
+AAL_CP::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+ int n;
+ ACE_INET_Addr from_addr;
+
+ ACE_DEBUG ((LM_DEBUG, "Activity occurred on handle %d!\n",
+ ACE_SOCK_Dgram::get_handle ()));
+ if ((n = ACE_SOCK_Dgram::recv (buf, sizeof buf, from_addr)) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "got buf = %s\n", buf));
+
+ return 0;
+}
+
+int
+AAL_CP::handle_timeout (const ACE_Time_Value &, const void *)
+{
+ ACE_DEBUG ((LM_DEBUG, "timed out for aa1\n"));
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ // Estabish call backs, and socket names.
+ if (argc != 4)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s localport remotehost remoteport\n",
+ argv[0]), -1);
+
+ ACE_Reactor reactor;
+ char buf[128];
+ u_short localport = ACE_OS::atoi (argv[1]);
+ u_short remoteport = ACE_OS::atoi (argv[3]);
+ char *remotehost = argv[2];
+
+ ACE_INET_Addr remote_addr (remoteport, remotehost);
+ ACE_INET_Addr local_addr (localport);
+
+ AAL_CP aal (local_addr);
+
+ if (localport == 10000) // HACK
+ {
+ ACE_OS::memcpy (buf, "Data to transmit", sizeof buf);
+ ACE_DEBUG ((LM_DEBUG, "sending data\n"));
+
+ for (size_t i = 0; i < 20; i++)
+ {
+ aal.send (buf, sizeof buf, remote_addr);
+ ACE_DEBUG ((LM_DEBUG, ".\n"));
+ ACE_OS::sleep (1);
+ }
+ }
+
+ // Read data from other side.
+ if (reactor.register_handler (&aal, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE_Reactor::register_handler"), -1);
+
+ if (reactor.schedule_timer (&aal, 0,
+ ACE_Time_Value (1, 0),
+ ACE_Time_Value (0, 3500000)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "ACE_Reactor::schedule_timer"), -1);
+
+ ACE_OS::memcpy (buf, "Data to transmit", sizeof buf);
+
+ for (;;)
+ {
+ // Wait at most two seconds.
+ ACE_Time_Value tv (2, 0);
+
+ reactor.handle_events (tv);
+
+ ACE_DEBUG ((LM_DEBUG, "return from handle events\n"));
+ aal.send (buf, sizeof buf, remote_addr);
+ ACE_DEBUG ((LM_DEBUG, ".\n"));
+ }
+
+ return 0;
+}
diff --git a/examples/Reactor/Dgram/Makefile b/examples/Reactor/Dgram/Makefile
new file mode 100644
index 00000000000..5c2204cd91a
--- /dev/null
+++ b/examples/Reactor/Dgram/Makefile
@@ -0,0 +1,135 @@
+#----------------------------------------------------------------------------
+# @(#)Makefile 1.1 10/18/96
+#
+# Makefile for a test of the CODgram and Dgram facilities and the Reactor
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+BIN = CODgram Dgram
+
+LSRC = CODgram.cpp Dgram.cpp
+
+LDLIBS =
+
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+
+BUILD = $(VBIN)
+
+INSTALL =
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.bin.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Dependencies
+#----------------------------------------------------------------------------
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+.obj/CODgram.o .shobj/CODgram.so: CODgram.cpp \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i \
+ $(WRAPPER_ROOT)/ace/SOCK_CODgram.h \
+ $(WRAPPER_ROOT)/ace/SOCK_CODgram.i
+.obj/Dgram.o .shobj/Dgram.so: Dgram.cpp \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram.i
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/examples/Reactor/Makefile b/examples/Reactor/Makefile
new file mode 100644
index 00000000000..4613709a2a2
--- /dev/null
+++ b/examples/Reactor/Makefile
@@ -0,0 +1,24 @@
+#----------------------------------------------------------------------------
+# @(#)Makefile 1.1 10/18/96
+#
+# Makefile for the Reactor tests
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+DIRS = Dgram \
+ Misc \
+ Multicast \
+ Ntalker
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nested.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nolocal.GNU
diff --git a/examples/Reactor/Misc/Makefile b/examples/Reactor/Misc/Makefile
new file mode 100644
index 00000000000..31d49795de7
--- /dev/null
+++ b/examples/Reactor/Misc/Makefile
@@ -0,0 +1,378 @@
+#----------------------------------------------------------------------------
+# @(#)Makefile 1.1 10/18/96
+#
+# Makefile for a test of the miscellaneous Reactor examples
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+BIN = pingpong \
+ notification \
+ signal_tester \
+ test_event_handler_t \
+ test_handle_set \
+ test_reactors \
+ test_signals \
+ test_time_value \
+ test_timer_queue
+
+LSRC = $(addsuffix .cpp,$(BIN))
+
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+
+BUILD = $(VBIN)
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.bin.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Dependencies
+#----------------------------------------------------------------------------
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+.obj/pingpong.o .shobj/pingpong.so: pingpong.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i
+.obj/notification.o .shobj/notification.so: notification.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Service_Config.h \
+ $(WRAPPER_ROOT)/ace/Service_Object.h \
+ $(WRAPPER_ROOT)/ace/Shared_Object.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Thread_Manager.h \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Proactor.h \
+ $(WRAPPER_ROOT)/ace/Message_Block.h \
+ $(WRAPPER_ROOT)/ace/Malloc.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
+ $(WRAPPER_ROOT)/ace/Memory_Pool.h \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Mem_Map.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/ReactorEx.h \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i \
+ $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h
+.obj/signal_tester.o .shobj/signal_tester.so: signal_tester.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Service_Config.h \
+ $(WRAPPER_ROOT)/ace/Service_Object.h \
+ $(WRAPPER_ROOT)/ace/Shared_Object.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Thread_Manager.h \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Proactor.h \
+ $(WRAPPER_ROOT)/ace/Message_Block.h \
+ $(WRAPPER_ROOT)/ace/Malloc.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
+ $(WRAPPER_ROOT)/ace/Memory_Pool.h \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Mem_Map.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/ReactorEx.h \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i \
+ $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h
+.obj/test_event_handler_t.o .shobj/test_event_handler_t.so: test_event_handler_t.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Event_Handler_T.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h
+.obj/test_handle_set.o .shobj/test_handle_set.so: test_handle_set.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h
+.obj/test_reactors.o .shobj/test_reactors.so: test_reactors.cpp \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i \
+ $(WRAPPER_ROOT)/ace/Service_Config.h \
+ $(WRAPPER_ROOT)/ace/Service_Object.h \
+ $(WRAPPER_ROOT)/ace/Shared_Object.h \
+ $(WRAPPER_ROOT)/ace/Thread_Manager.h \
+ $(WRAPPER_ROOT)/ace/Proactor.h \
+ $(WRAPPER_ROOT)/ace/Message_Block.h \
+ $(WRAPPER_ROOT)/ace/Malloc.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.h \
+ $(WRAPPER_ROOT)/ace/Malloc_T.cpp \
+ $(WRAPPER_ROOT)/ace/Malloc_T.i \
+ $(WRAPPER_ROOT)/ace/Memory_Pool.h \
+ $(WRAPPER_ROOT)/ace/Mem_Map.h \
+ $(WRAPPER_ROOT)/ace/ReactorEx.h \
+ $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \
+ $(WRAPPER_ROOT)/ace/Task.h \
+ $(WRAPPER_ROOT)/ace/Message_Queue.h \
+ $(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \
+ $(WRAPPER_ROOT)/ace/Message_Queue.cpp \
+ $(WRAPPER_ROOT)/ace/Message_Queue.i \
+ $(WRAPPER_ROOT)/ace/Task.cpp \
+ $(WRAPPER_ROOT)/ace/Module.h \
+ $(WRAPPER_ROOT)/ace/Module.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.h \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \
+ $(WRAPPER_ROOT)/ace/Stream_Modules.i \
+ $(WRAPPER_ROOT)/ace/Module.i \
+ $(WRAPPER_ROOT)/ace/Task.i
+.obj/test_signals.o .shobj/test_signals.so: test_signals.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i
+.obj/test_time_value.o .shobj/test_time_value.so: test_time_value.cpp \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i
+.obj/test_timer_queue.o .shobj/test_timer_queue.so: test_timer_queue.cpp \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/examples/Reactor/Misc/notification.cpp b/examples/Reactor/Misc/notification.cpp
new file mode 100644
index 00000000000..45836446b5a
--- /dev/null
+++ b/examples/Reactor/Misc/notification.cpp
@@ -0,0 +1,249 @@
+#include "ace/Log_Msg.h"
+// @(#)notification.cpp 1.1 10/18/96
+
+#include "ace/Service_Config.h"
+#include "ace/Thread.h"
+
+#if defined (ACE_HAS_THREADS)
+
+class Thread_Handler : public ACE_Event_Handler
+ // = TITLE
+ // Illustrate how the ACE_Reactor's thread-safe event notification
+ // mechanism works.
+ //
+ // = DESCRIPTION
+ // Handle timeouts in the main thread via the ACE_Reactor and I/O
+ // events in a separate thread. Just before the separate I/O thread
+ // exits it notifies the ACE_Reactor in the main thread using the
+ // ACE_Reactor's notification mechanism.
+{
+public:
+ Thread_Handler (int delay, int interval, int n_threads);
+ Thread_Handler (size_t id): id_ (id) {}
+
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+ // Handle signals.
+
+ virtual int handle_exception (ACE_HANDLE);
+ // Print data from main thread.
+
+ virtual int handle_output (ACE_HANDLE);
+ // Print data from main thread.
+
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *);
+ // Handle timeout events in the main thread.
+
+ virtual int handle_input (ACE_HANDLE);
+ // General notification messages to the Reactor.
+
+ virtual int notify (void);
+ // Perform notifications.
+
+ virtual int svc (void);
+ // Handle I/O events in a separate threads.
+
+private:
+ static void *svc_run (void *);
+ // Glues C++ to C thread library functions.
+
+ size_t id_;
+ // ID passed in by Thread_Handler constructor.
+
+ // = Timing variables.
+ // Delay factor for timer-driven I/O.
+ static ACE_Time_Value delay_;
+
+ // Interval factor for Event_Handler timer.
+ static ACE_Time_Value interval_;
+};
+
+// Delay factor for timer-driven I/O.
+ACE_Time_Value Thread_Handler::delay_;
+
+// Interval factor for Event_Handler timer.
+ACE_Time_Value Thread_Handler::interval_;
+
+Thread_Handler::Thread_Handler (int delay,
+ int interval,
+ int n_threads)
+{
+ delay_.set (delay);
+ interval_.set (interval);
+
+ ACE_Sig_Set sig_set;
+
+ sig_set.sig_add (SIGQUIT);
+ sig_set.sig_add (SIGINT);
+
+ this->id_ = 0;
+
+ if (ACE::register_stdin_handler (this,
+ ACE_Service_Config::reactor (),
+ ACE_Service_Config::thr_mgr ()) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "register_stdin_handler"));
+
+ else if (ACE_Service_Config::reactor ()->register_handler (sig_set, this) == -1)
+ ACE_ERROR ((LM_ERROR, "(%t) %p\n", "register_handler"));
+
+ else if (ACE_Service_Config::reactor ()->schedule_timer
+ (this, 0, Thread_Handler::delay_, Thread_Handler::interval_) == -1)
+ ACE_ERROR ((LM_ERROR, "(%t) %p\n", "schedule_timer"));
+
+ // Set up this thread's signal mask, which is inherited by the
+ // threads it spawns.
+
+ ACE_Thread::sigsetmask (SIG_BLOCK, sig_set);
+
+ // Create N new threads of control Thread_Handlers.
+
+ for (size_t i = 0; i < n_threads; i++)
+ if (ACE_Thread::spawn (&Thread_Handler::svc_run,
+ new Thread_Handler (i + 1),
+ THR_NEW_LWP | THR_DETACHED) != 0)
+ ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Thread::spawn"));
+
+ // Unblock signal set so that only this thread receives them!
+ ACE_Thread::sigsetmask (SIG_UNBLOCK, sig_set);
+}
+
+// Test stdin handling (can use select to demultiplex HANDLEs)
+
+int
+Thread_Handler::handle_input (ACE_HANDLE handle)
+{
+ char buf[BUFSIZ];
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ if (n > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) %*s", n, buf));
+ return this->notify ();
+ }
+ else
+ return -1;
+}
+
+int
+Thread_Handler::notify (void)
+{
+ // Just do something to test the ACE_Reactor's multi-thread
+ // capabilities...
+
+ if (ACE_Service_Config::reactor ()->notify
+ (this, ACE_Event_Handler::EXCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) %p\n", "notify"), -1);
+
+ else if (ACE_Service_Config::reactor ()->notify
+ (this, ACE_Event_Handler::WRITE_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) %p\n", "notify"), -1);
+
+ return 0;
+}
+
+// Perform a task that will test the ACE_Reactor's multi-threading
+// capabilities in separate threads.
+
+int
+Thread_Handler::svc (void)
+{
+ for (;;)
+ {
+ if (Thread_Handler::delay_.sec () > 0)
+ // Block for delay_.secs () / 2, then notify the Reactor.
+ ACE_OS::sleep (Thread_Handler::delay_.sec () / 2);
+
+ this->notify ();
+ }
+ return 0;
+}
+
+// Test signal handling.
+
+int
+Thread_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) received signal %S\n", signum));
+
+ switch (signum)
+ {
+ case SIGINT:
+ case SIGQUIT:
+ ACE_ERROR ((LM_ERROR,
+ "(%t) ******************** shutting down %n on signal %S\n",
+ signum));
+ ACE_Service_Config::end_reactor_event_loop ();
+ }
+ return 0;
+}
+
+int
+Thread_Handler::handle_timeout (const ACE_Time_Value &time,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) received timeout at (%u, %u)\n",
+ time.sec (), time.usec ()));
+ return 0;
+}
+
+// Called by the ACE_Reactor when it receives a notification.
+
+int
+Thread_Handler::handle_exception (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) handle_exception received notification from id %d\n",
+ this->id_));
+ return 0;
+}
+
+// Called by the ACE_Reactor when it receives a notification.
+
+int
+Thread_Handler::handle_output (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) handle_output received notification from id %d\n",
+ this->id_));
+ return 0;
+}
+
+// "Shim" function that integrates C thread API with C++.
+
+void *
+Thread_Handler::svc_run (void *eh)
+{
+ Thread_Handler *this_handler = (Thread_Handler *) eh;
+
+ return this_handler->svc () == 0 ? 0 : (void *) -1;
+}
+
+int
+main (int argc, char *argv[])
+{
+ // Required to initialize the Service Configurator.
+ ACE_Service_Config daemon (argv[0]);
+
+ if (argc != 4)
+ ACE_ERROR ((LM_ERROR,
+ "usage: %s delay interval n_threads%a\n",
+ argv[0], 1));
+
+ int delay = ACE_OS::atoi (argv[1]);
+ int interval = ACE_OS::atoi (argv[2]);
+ size_t n_threads = ACE_OS::atoi (argv[3]);
+
+ Thread_Handler thr_handler (delay, interval, n_threads);
+
+ ACE_Service_Config::run_reactor_event_loop ();
+ ACE_DEBUG ((LM_DEBUG, "exiting from main%a\n", 1));
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "threads not supported on this platform\n"), -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/examples/Reactor/Misc/pingpong.cpp b/examples/Reactor/Misc/pingpong.cpp
new file mode 100644
index 00000000000..a44267f4e82
--- /dev/null
+++ b/examples/Reactor/Misc/pingpong.cpp
@@ -0,0 +1,241 @@
+/* Simple program that illustrates all the features of the ACE_Reactor:
+// @(#)pingpong.cpp 1.1 10/18/96
+
+
+ 1. I/O event demultiplexing
+ 2. Signal-based demultiplexing
+ 3. Timer-based demultiplexing
+
+ To test this program, compile it and then execute it as follows:
+
+ % ./pingpong hello
+
+ You should see lots of the following output:
+
+ writing <4> [7860]
+ writing <4> [7860]
+ writing <4> [7860]
+ writing <4> [7860]
+ reading <5> (7860) [1] = hello
+ writing <4> [7860]
+ writing <5> [7861]
+ reading <4> (7861) [2] = hello
+ reading <5> (7860) [2] = hello
+ writing <4> [7860]
+ writing <5> [7861]
+ reading <4> (7861) [3] = hello
+ reading <5> (7860) [3] = hello
+
+ After 10 seconds you'll see the following:
+
+ ./pingpong: shutting down tester (pid = 7861)
+ ./pingpong: shutting down tester (pid = 7860)
+
+ and the program will stop. If you'd like to
+ stop it earlier, just hit the control-C sequence
+ and you'll see the same messages. */
+
+#include "ace/Log_Msg.h"
+#include "ace/Synch.h"
+#include "ace/Reactor.h"
+#include "ace/Pipe.h"
+
+class Ping_Pong : public ACE_Test_and_Set<ACE_Null_Mutex, sig_atomic_t>
+{
+public:
+ Ping_Pong (char b[], ACE_HANDLE f);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_output (ACE_HANDLE);
+ virtual int handle_timeout (const ACE_Time_Value &, const void *);
+
+private:
+ char buf_[BUFSIZ];
+ // Buffer to send.
+
+ size_t buflen_;
+ // Length of the buffer to send.
+
+ int pid_;
+ // Process ID.
+
+ ACE_HANDLE handle_;
+ // Open handle.
+};
+
+Ping_Pong::Ping_Pong (char b[], ACE_HANDLE f)
+ : handle_ (f),
+ buflen_ (ACE_OS::strlen (b) + 1 + (2 * sizeof (int))),
+ pid_ (ACE_OS::getpid ())
+{
+ *((int *) this->buf_) = (int) this->pid_;
+ *((int *) (this->buf_ + sizeof (int))) = 0;
+ ACE_OS::strcpy (this->buf_ + (2 * sizeof (int)), b);
+ this->buf_[this->buflen_ - 1] = '\n';
+ this->buf_[this->buflen_] = '\0';
+}
+
+ACE_HANDLE
+Ping_Pong::get_handle (void) const
+{
+ return this->handle_;
+}
+
+int
+Ping_Pong::handle_input (ACE_HANDLE)
+{
+#if defined (ACE_HAS_STREAM_PIPES)
+ // We can rely on record-oriented reads...
+
+ ssize_t n = ACE::recv (this->handle_, this->buf_, this->buflen_);
+
+ if (n != this->buflen_)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) reading [%d] %p\n", handle_, "read"), -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reading <%d> (%d) [%d] = %s\n",
+ this->handle_,
+ *(int *) this->buf_,
+ *(int *) (this->buf_ + sizeof (int)),
+ this->buf_ + (2 * sizeof (int))));
+#else
+ ssize_t n = ACE::recv (this->handle_, this->buf_, sizeof this->buf_);
+
+ if (n == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "[%d] %p\n", handle_, "read"), -1);
+
+ n -= (2 * sizeof (int));
+ char *buf = this->buf_ + (2 * sizeof (int));
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) reading <%d> = %*s\n",
+ this->handle_, n, buf));
+#endif /* ACE_HAS_STREAM_PIPES */
+ return 0;
+}
+
+int
+Ping_Pong::handle_output (ACE_HANDLE)
+{
+#if defined (ACE_HAS_STREAM_PIPES)
+ // We can rely on record-oriented reads...
+
+ (*(int *) (this->buf_)) = this->pid_;
+ (*(int *) (this->buf_ + sizeof (int)))++;
+ if (ACE::send (this->handle_, this->buf_, this->buflen_) == -1)
+ return -1;
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) writing <%d> [%d]\n",
+ this->handle_, this->pid_));
+ return 0;
+ }
+#else
+ if (ACE::send (this->handle_, this->buf_, this->buflen_) == -1)
+ return -1;
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) writing <%d>\n", this->handle_));
+ return 0;
+ }
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+int
+Ping_Pong::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ this->set (1);
+ return 0;
+}
+
+// Contains the string to "pingpong" back and forth...
+static char *string_name;
+
+// Wait for 10 seconds and then shut down.
+static const int SHUTDOWN_TIME = 10;
+
+#if defined (ACE_WIN32)
+static ACE_Barrier barrier (3);
+
+static void *
+worker (void *arg)
+{
+ ACE_HANDLE handle = (ACE_HANDLE) arg;
+
+ run_svc (handle);
+ barrier.wait ();
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) %n: shutting down tester\n"));
+ return 0;
+}
+#endif /* ACE_WIN32 */
+
+static void
+run_svc (ACE_HANDLE handle)
+{
+ ACE_Reactor reactor;
+
+ Ping_Pong callback (string_name, handle);
+
+ // Register the callback object for the various I/O, signal, and
+ // timer-based events.
+
+ if (reactor.register_handler (&callback,
+ ACE_Event_Handler::READ_MASK
+ | ACE_Event_Handler::WRITE_MASK) == -1
+ || reactor.register_handler (SIGINT, &callback) == -1
+ || reactor.schedule_timer (&callback, 0, SHUTDOWN_TIME) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "reactor", 1));
+
+ // Main event loop (one per process).
+
+ while (callback.is_set () == 0)
+ reactor.handle_events ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (argc != 2)
+ ACE_ERROR ((LM_ERROR, "usage: %n string\n%a", 1));
+
+ string_name = argv[1];
+
+ ACE_HANDLE handles[2];
+
+ // Create a pipe and initialize the handles.
+ ACE_Pipe pipe (handles);
+
+#if defined (ACE_WIN32)
+ if (ACE_Thread::spawn (ACE_THR_FUNC (worker),
+ (void *) handles[0],
+ THR_DETACHED) == -1
+ || ACE_Thread::spawn (ACE_THR_FUNC (worker),
+ (void *) handles[1],
+ THR_DETACHED) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "spawn", 1));
+
+ barrier.wait ();
+
+#else
+ pid_t pid = ACE_OS::fork ();
+
+ if (pid == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "fork", 1));
+
+ // Resync the ACE_Log_Msg notion of process id and program name.
+ ACE_LOG_MSG->sync (argv[0]);
+
+ run_svc (handles[pid == 0]);
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) %n: shutting down tester\n"));
+#endif /* ACE_WIN32 */
+
+ if (pipe.close () == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "close"));
+
+ return 0;
+}
diff --git a/examples/Reactor/Misc/signal_tester.cpp b/examples/Reactor/Misc/signal_tester.cpp
new file mode 100644
index 00000000000..1631c00b2d0
--- /dev/null
+++ b/examples/Reactor/Misc/signal_tester.cpp
@@ -0,0 +1,221 @@
+// Perform an extensive test of the ACE_Reactor's event dispatching
+// @(#)signal_tester.cpp 1.1 10/18/96
+
+// mechanisms. These mechanisms illustrate how signals, I/O, and
+// timeout events can all be handled within the same framework. In
+// addition, this example illustrates how to use the ACE_Reactor for
+// devices that perform I/O via signals (such as SVR4 message queues).
+
+#include "ace/Log_Msg.h"
+#include "ace/Service_Config.h"
+
+// Used to shut down the event loop.
+static sig_atomic_t done = 0;
+
+// This class illustrates how to handle signal-driven I/O using the
+// ACE_Reactor framework. Note that signals may be caught and
+// processed without requiring the use of global signal handler
+// functions or global signal handler data.
+
+class Sig_Handler : public ACE_Event_Handler
+{
+public:
+ Sig_Handler (void);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int shutdown (ACE_HANDLE, ACE_Reactor_Mask);
+ virtual int handle_signal (ACE_HANDLE signum, siginfo_t * = 0,
+ ucontext_t * = 0);
+
+private:
+ ACE_HANDLE handle_;
+};
+
+// A dummy_handle is required to reserve a slot in the ACE_Reactor's
+// descriptor table.
+
+Sig_Handler::Sig_Handler (void)
+{
+ // Assign the Sig_Handler a dummy I/O descriptor. Note that even
+ // though we open this file "Write Only" we still need to use the
+ // ACE_Event_Handler::NULL_MASK when registering this with the
+ // ACE_Reactor (see below).
+ this->handle_ = ACE_OS::open (ACE_DEV_NULL, O_WRONLY);
+ ACE_ASSERT (this->handle_ != -1);
+
+ // Register signal handler object. Note that NULL_MASK is used to
+ // keep the ACE_Reactor from calling us back on the "/dev/null"
+ // descriptor.
+ if (ACE_Service_Config::reactor ()->register_handler
+ (this, ACE_Event_Handler::NULL_MASK) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "register_handler", 1));
+
+ // Create a sigset_t corresponding to the signals we want to catch.
+ ACE_Sig_Set sig_set;
+
+ sig_set.sig_add (SIGINT);
+ sig_set.sig_add (SIGQUIT);
+ sig_set.sig_add (SIGALRM);
+
+ // Register the signal handler object to catch the signals.
+ if (ACE_Service_Config::reactor ()->register_handler (sig_set, this) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "register_handler", 1));
+}
+
+// Called by the ACE_Reactor to extract the fd.
+
+ACE_HANDLE
+Sig_Handler::get_handle (void) const
+{
+ return this->handle_;
+}
+
+// In a real application, this method would be where the read on the
+// signal-driven I/O device would occur asynchronously. For now we'll
+// just print a greeting to let you know that everything is working
+// properly!
+
+int
+Sig_Handler::handle_input (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG, "handling asynchonrous input...\n"));
+ return 0;
+}
+
+// In a real application, this method would do any cleanup activities
+// required when shutting down the I/O device.
+
+int
+Sig_Handler::shutdown (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "closing down Sig_Handler...\n"));
+ return 0;
+}
+
+// This method handles all the signals that are being caught by this
+// object. In our simple example, we are simply catching SIGALRM,
+// SIGINT, and SIGQUIT. Anything else is logged and ignored.
+//
+// There are several advantages to using this approach. First,
+// the behavior triggered by the signal is handled in the main event
+// loop, rather than in the signal handler. Second, the ACE_Reactor's
+// signal handling mechanism eliminates the need to use global signal
+// handler functions and data.
+
+int
+Sig_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *)
+{
+ ACE_DEBUG ((LM_DEBUG, "received signal %S\n", signum));
+
+ switch (signum)
+ {
+ case SIGALRM:
+ // Rearm the alarm.
+ ACE_OS::alarm (4);
+ break;
+ case SIGINT:
+ // Tell the ACE_Reactor to enable the ready bit for
+ // this->handle_. The ACE_Reactor will subsequently call the
+ // Sig_Handler::handle_input method from within its event loop.
+ return ACE_Service_Config::reactor ()->ready_ops
+ (this->handle_, ACE_Event_Handler::READ_MASK, ACE_Reactor::ADD_MASK);
+ case SIGQUIT:
+ ACE_DEBUG ((LM_DEBUG, "%S: shutting down signal tester\n", signum));
+ ACE_Service_Config::end_reactor_event_loop ();
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ "%S: not handled, returning to program\n", signum));
+ break;
+ }
+ return 0;
+}
+
+// This class illustrates that the ACE_Reactor can handle signals,
+// STDIO, and timeouts using the same mechanisms.
+
+class STDIN_Handler : public ACE_Event_Handler
+{
+public:
+ STDIN_Handler (void);
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *arg);
+};
+
+STDIN_Handler::STDIN_Handler (void)
+{
+ if (ACE::register_stdin_handler (this,
+ ACE_Service_Config::reactor (),
+ ACE_Service_Config::thr_mgr ()) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "register_stdin_handler"));
+
+ // Register the STDIN_Handler to be dispatched once every second.
+ else if (ACE_Service_Config::reactor ()->schedule_timer
+ (this, 0, ACE_Time_Value (1), ACE_Time_Value (1)) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "schedule_timer", 1));
+}
+
+int
+STDIN_Handler::handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+{
+ ACE_DEBUG ((LM_DEBUG, "timeout occurred at %d sec, %d usec\n",
+ tv.sec (), tv.usec ()));
+ return 0;
+}
+
+// Read from input descriptor and write to stdout descriptor.
+
+int
+STDIN_Handler::handle_input (ACE_HANDLE handle)
+{
+ ssize_t n;
+ char buf[BUFSIZ];
+
+ switch (n = ACE_OS::read (handle, buf, sizeof buf))
+ {
+ case -1:
+ if (errno == EINTR)
+ return 0;
+ /* NOTREACHED */
+ else
+ ACE_ERROR ((LM_ERROR, "%p\n", "read"));
+ /* FALLTHROUGH */
+ case 0:
+ ACE_Service_Config::end_reactor_event_loop ();
+ break;
+ default:
+ {
+ ssize_t result = ACE::write_n (ACE_STDOUT, buf, n);
+
+ if (result != n)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "write"),
+ result == -1 && errno == EINTR ? 0 : -1);
+ }
+ }
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Service_Config daemon (argv [0]);
+
+ // Signal handler.
+ Sig_Handler sh;
+
+ // Define an I/O handler object.
+ STDIN_Handler ioh;
+
+ // Optionally start the alarm.
+ if (argc > 1)
+ ACE_OS::alarm (4);
+
+ // Loop handling signals and I/O events until SIGQUIT occurs.
+
+ while (daemon.reactor_event_loop_done () == 0)
+ daemon.run_reactor_event_loop ();
+
+ return 0;
+}
diff --git a/examples/Reactor/Misc/test_event_handler_t.cpp b/examples/Reactor/Misc/test_event_handler_t.cpp
new file mode 100644
index 00000000000..a28108baf10
--- /dev/null
+++ b/examples/Reactor/Misc/test_event_handler_t.cpp
@@ -0,0 +1,45 @@
+#include "ace/Log_Msg.h"
+// @(#)test_event_handler_t.cpp 1.1 10/18/96
+
+#include "ace/Event_Handler_T.h"
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+
+class ACE_Sig_Handler
+{
+public:
+ ACE_Sig_Handler (void) {}
+ virtual ACE_HANDLE get_handle (void) const { return 0; }
+ virtual void set_handle (ACE_HANDLE) {}
+ virtual int handle_async_io (ACE_HANDLE) { return 0; }
+ virtual int shutdown (ACE_HANDLE, ACE_Reactor_Mask) { return 0; }
+ virtual int signal_handler (ACE_HANDLE signum
+#if defined (ACE_HAS_SIGINFO_T)
+ , siginfo_t * = 0, ucontext_t * = 0
+#endif /* ACE_HAS_SIGINFO_T */
+ )
+ {
+ return 0;
+ }
+};
+
+int
+main (void)
+{
+ typedef ACE_Event_Handler_T<ACE_Sig_Handler> EH_SH;
+
+ // Tie the ACE_Event_Handler_T together with the methods from ACE_Sig_Handler.
+ EH_SH tied_sh (new ACE_Sig_Handler, 1,
+ &ACE_Sig_Handler::get_handle,
+ &ACE_Sig_Handler::handle_async_io,
+ &ACE_Sig_Handler::shutdown,
+ &ACE_Sig_Handler::signal_handler);
+ return 0;
+}
+#else
+int
+main (void)
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "your platform does not support template typedefs\n"), 1);
+}
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
diff --git a/examples/Reactor/Misc/test_handle_set.cpp b/examples/Reactor/Misc/test_handle_set.cpp
new file mode 100644
index 00000000000..65e7db3fc67
--- /dev/null
+++ b/examples/Reactor/Misc/test_handle_set.cpp
@@ -0,0 +1,75 @@
+#include "ace/Log_Msg.h"
+// @(#)test_handle_set.cpp 1.1 10/18/96
+
+#include "ace/Handle_Set.h"
+
+#define IS_ODD(X) (((X) & 1) != 0)
+
+void
+test1 (int count)
+{
+ int duplicates = 0;
+ int sets = 0;
+ int clears = 0;
+
+ ACE_Handle_Set handle_set;
+
+ ACE_OS::srand (ACE_OS::time (0L));
+
+ for (int i = 0; i < count; i++)
+ {
+ int i = int (ACE_OS::rand () % ACE_Handle_Set::MAXSIZE);
+
+ if (IS_ODD (i))
+ {
+ if (handle_set.is_set (i))
+ duplicates++;
+
+ handle_set.set_bit (i);
+ sets++;
+ }
+ else
+ {
+ if (handle_set.is_set (i))
+ duplicates--;
+
+ handle_set.clr_bit (i);
+ clears++;
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "count = %d, set_size = %d, duplicates = %d\n",
+ count, handle_set.num_set (), (sets - clears) == duplicates));
+}
+
+void
+test2 (void)
+{
+ ACE_Handle_Set handle_set;
+ ACE_HANDLE handle;
+
+ handle_set.set_bit (0);
+ handle_set.set_bit (1);
+ handle_set.set_bit (32);
+ handle_set.set_bit (63);
+ handle_set.set_bit (64);
+ handle_set.set_bit (65);
+ handle_set.set_bit (122);
+ handle_set.set_bit (129);
+ handle_set.set_bit (245);
+ handle_set.set_bit (255);
+
+ for (ACE_Handle_Set_Iterator fi (handle_set);
+ (handle = fi ()) != -1;
+ ++fi)
+ ACE_DEBUG ((LM_DEBUG, "handle = %d\n", handle));
+}
+
+int
+main (int argc, char *argv[])
+{
+ int count = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_Handle_Set::MAXSIZE;
+ test1 (count);
+ test2 ();
+}
+
diff --git a/examples/Reactor/Misc/test_reactors.cpp b/examples/Reactor/Misc/test_reactors.cpp
new file mode 100644
index 00000000000..81bc1c3a20d
--- /dev/null
+++ b/examples/Reactor/Misc/test_reactors.cpp
@@ -0,0 +1,205 @@
+// Perform a torture test of multiple ACE_Reactors and ACE_Tasks in
+// @(#)test_reactors.cpp 1.1 10/18/96
+
+// the same process... Thanks to Detlef Becker for contributing this.
+
+#include "ace/Reactor.h"
+#include "ace/Synch.h"
+#include "ace/Service_Config.h"
+#include "ace/Task.h"
+
+#if defined (ACE_HAS_THREADS)
+
+static const int NUM_INVOCATIONS = 10;
+static const int MAX_TASKS = 20;
+
+class Test_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Test_Task (void);
+ ~Test_Task (void);
+
+ virtual int open (void *args = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *, ACE_Time_Value *tv = 0);
+ virtual int svc (void);
+
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE fd,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ ACE_Reactor *r_;
+ int handled_;
+
+ static int task_count_;
+};
+
+int Test_Task::task_count_ = 0;
+
+static ACE_Atomic_Op<ACE_Thread_Mutex, u_long> done_count = MAX_TASKS * 2;
+
+static ACE_Recursive_Thread_Mutex reclock_;
+
+Test_Task::Test_Task (void)
+ : handled_ (0)
+{
+ ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, reclock_);
+
+ Test_Task::task_count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) TT+ Test_Task::task_count_ = %d\n",
+ Test_Task::task_count_));
+}
+
+Test_Task::~Test_Task (void)
+{
+ ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, reclock_);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) TT- Test_Task::task_count_ = %d\n",
+ Test_Task::task_count_));
+}
+
+int
+Test_Task::open (void *args)
+{
+ r_ = (ACE_Reactor *) args;
+ return this->activate (THR_NEW_LWP);
+}
+
+int
+Test_Task::close (u_long flags)
+{
+ ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, reclock_, -1);
+
+ Test_Task::task_count_--;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) close Test_Task::task_count_ = %d\n",
+ Test_Task::task_count_));
+ return 0;
+}
+
+int
+Test_Task::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+ return 0;
+}
+
+int
+Test_Task::svc (void)
+{
+ for (int i = 0; i < NUM_INVOCATIONS; i++)
+ {
+ ACE_OS::thr_yield ();
+
+ // ACE_DEBUG ((LM_DEBUG, "(%t) calling notify %d\n", i));
+
+ if (r_->notify (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) %p\n", "notify"), -1);
+
+ // ACE_DEBUG ((LM_DEBUG, "(%t) leaving notify %d\n", i));
+ }
+
+ return 0;
+}
+
+int
+Test_Task::handle_close (ACE_HANDLE fd,
+ ACE_Reactor_Mask close_mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) handle_close\n"));
+ return 0;
+}
+
+int
+Test_Task::handle_input (ACE_HANDLE fd)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) handle_input\n"));
+
+ this->handled_++;
+
+ if (this->handled_ == NUM_INVOCATIONS)
+ {
+ done_count--;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) handle_input, handled_ = %d, done_count = %d\n",
+ this->handled_, (u_long) done_count));
+ }
+
+ ACE_OS::thr_yield ();
+ return -1;
+}
+
+static void *
+worker (void *args)
+{
+ ACE_Thread_Control tc (ACE_Service_Config::thr_mgr ());
+ ACE_Reactor *reactor = (ACE_Reactor *) args;
+
+ reactor->owner (ACE_Thread::self ());
+
+ ACE_Time_Value timeout (4);
+
+ for (;;)
+ {
+ //ACE_DEBUG ((LM_DEBUG, "(%t) calling handle_events\n"));
+
+ switch (reactor->handle_events (timeout))
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "reactor"), 0);
+ /* NOTREACHED */
+ case 0:
+ ACE_ERROR_RETURN ((LM_ERROR, "timeout\n"), 0);
+ /* NOTREACHED */
+ }
+
+ // ACE_DEBUG ((LM_DEBUG, "(%t) done with handle_events\n"));
+
+ }
+
+ return 0;
+}
+
+int
+main (void)
+{
+ ACE_Reactor *react1 = ACE_Service_Config::reactor ();
+ ACE_Reactor *react2 = new ACE_Reactor ();
+ Test_Task tt1[MAX_TASKS];
+ Test_Task tt2[MAX_TASKS];
+
+ for (int i = 0; i < MAX_TASKS; i++)
+ {
+ tt1[i].open (react1);
+ tt2[i].open (react2);
+ }
+
+ if (ACE_Service_Config::thr_mgr ()->spawn
+ (ACE_THR_FUNC (worker), (void *) react1, THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ else if (ACE_Service_Config::thr_mgr ()->spawn
+ (ACE_THR_FUNC (worker), (void *) react2, THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ ACE_Service_Config::thr_mgr ()->wait ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) done\n"));
+
+ return 42;
+}
+
+#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION)
+template class ACE_Atomic_Op<ACE_Thread_Mutex, u_long>;
+#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */
+
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/examples/Reactor/Misc/test_signals.cpp b/examples/Reactor/Misc/test_signals.cpp
new file mode 100644
index 00000000000..b3725f66c89
--- /dev/null
+++ b/examples/Reactor/Misc/test_signals.cpp
@@ -0,0 +1,226 @@
+// Test the ability of the Reactor/Signal_Handler to register multiple
+// @(#)test_signals.cpp 1.1 10/18/96
+
+// handler per-signal.
+
+/* This test works as follows:
+
+ 1. To test the "original" semantics of ACE (i.e., only one
+ ACE_Event_Handler can be registered per signal), you don't
+ need to do anything special. Existing programs work the
+ same since giving the Reactor's constructor a 0 value
+ (which is the default argument, BTW) instructs it to behave
+ as before. When a 0 is given, the ACE_Reactor's
+ constructor/open method creates an instance of
+ ACE_Sig_Handler and assigns this to an internal pointer.
+ This pointer is then used to dispatch all signal-related
+ methods within the Reactor. The default ACE_Sig_Handler
+ only allows *one* ACE_Event_Handler to be registered
+ per-signal.
+
+ To run this version of the test do the following:
+
+ % ./test-signal
+ ./test_signals
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 0, 0) with count = 1
+ waiting for SIGINT or SIGQUIT
+ ^\
+ signal Quit occurred in Sig_Handler_2 (fruity, 0, 0) with count = 2
+ shutting down SIGQUIT in Sig_Handler_2 (fruity, 0, 0)
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 0, 0) with count = 3
+ waiting for SIGINT or SIGQUIT
+ ^\Quit (core dumped)
+
+ Note that in this test only one handler (the last one --
+ "Sig_Handler_2 (fruity)") is actually registered. BTW, the
+ core dump is the expected behavior since the default
+ disposition is restored when there are no more handlers
+ (see the code below).
+
+ 2. To test the "multiple handlers per-signal semantics", you
+ need to pass the constructor/open method of the ACE_Reactor
+ a pointer to a an instance of ACE_Sig_Handlers (note the
+ plural "s"). ACE_Sig_Handlers is a class that derives from
+ ACE_Sig_Handler. The difference between these two classes
+ is that (1) ACE_Sig_Handlers::register_signal allows
+ multiple ACE_Event_Handlers to be registered per-signal and
+ (2) it enables SA_RESTART by default. This class also
+ implements Detlef Becker's algorithm for integrating ACE
+ signal handling with 3rd party libraries.
+
+ To run this version of the test do the following:
+
+ % ./test_signals 1
+
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in external handler!
+ signal Interrupt occurred in Sig_Handler_1 (howdy, 3, 1) with count = 1
+ shutting down SIGINT in Sig_Handler_1 (howdy, 3, 1)
+ signal Interrupt occurred in Sig_Handler_1 (doody, 5, 4) with count = 1
+ shutting down SIGINT in Sig_Handler_1 (doody, 5, 4)
+ signal Interrupt occurred in Sig_Handler_2 (tutty, 7, 6) with count = 1
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 9, 8) with count = 1
+ waiting for SIGINT or SIGQUIT
+ ^\
+ signal Quit occurred in Sig_Handler_1 (howdy, 3, 1) with count = 2
+ shutting down SIGQUIT in Sig_Handler_1 (howdy, 3, 1)
+ signal Quit occurred in Sig_Handler_1 (doody, 5, 4) with count = 2
+ shutting down SIGQUIT in Sig_Handler_1 (doody, 5, 4)
+ signal Quit occurred in Sig_Handler_2 (tutty, 7, 6) with count = 2
+ shutting down SIGQUIT in Sig_Handler_2 (tutty, 7, 6)
+ signal Quit occurred in Sig_Handler_2 (fruity, 9, 8) with count = 2
+ shutting down SIGQUIT in Sig_Handler_2 (fruity, 9, 8)
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in external handler!
+ signal Interrupt occurred in Sig_Handler_2 (tutty, 7, 6) with count = 3
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 9, 8) with count = 3
+ waiting for SIGINT or SIGQUIT
+ ^\Quit (core dumped)
+
+ When this test begins all four handlers are registered and
+ dispatched when a SIGINT or SIGQUIT occurs. After the
+ first SIGINT, the handle_signal method of the Sig_Handler_1
+ objects unregister themselves. At that point there are 4
+ SIGQUIT handlers left, but only 2 of our SIGINT handlers
+ left (and the 1 external handler). After the first
+ SIGQUIT, there are no SIGQUIT handlers left since they all
+ deregister themselves (which restores the "SIG_DFL"
+ disposition). On the second SIGINT there are only 3
+ handlers left (2 of ours and 1 external). Finally, on the
+ second SIGQUIT we exit and dump core since that's what
+ happens with the default disposition for SIGQUIT. */
+
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+
+class Sig_Handler_1 : public ACE_Event_Handler
+{
+public:
+ Sig_Handler_1 (ACE_Reactor &reactor, char *msg)
+ : msg_ (msg),
+ count_ (0),
+ reactor_ (reactor)
+ {
+ // Register the signal handlers.
+ this->quit_sigkey_ = reactor.register_handler (SIGQUIT, this);
+ this->int_sigkey_ = reactor.register_handler (SIGINT, this);
+
+ if (this->quit_sigkey_ == -1 || this->int_sigkey_ == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "register_handler"));
+ }
+
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *)
+ {
+ this->count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nsignal %S occurred in Sig_Handler_1 (%s, %d, %d) with count = %d",
+ signum, this->msg_, this->int_sigkey_, this->quit_sigkey_, this->count_));
+ if (this->count_ != 1 && signum == SIGQUIT)
+ {
+ if (this->reactor_.remove_handler (SIGQUIT, 0, 0,
+ this->quit_sigkey_) == -1)
+ ACE_ERROR ((LM_ERROR, "\n%p", "remove_handler"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "\nshutting down SIGQUIT in Sig_Handler_1 (%s, %d, %d)",
+ this->msg_, this->int_sigkey_, this->quit_sigkey_));
+ }
+ else if (this->count_ != 2 && signum == SIGINT)
+ {
+ if (this->reactor_.remove_handler (SIGINT, 0, 0,
+ this->int_sigkey_) == -1)
+ ACE_ERROR ((LM_ERROR, "\n%p", "remove_handler"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "\nshutting down SIGINT in Sig_Handler_1 (%s, %d, %d)",
+ this->msg_, this->int_sigkey_, this->quit_sigkey_));
+ }
+ return 0;
+ }
+
+protected:
+ char *msg_;
+ int count_;
+ int int_sigkey_;
+ int quit_sigkey_;
+ ACE_Reactor &reactor_;
+};
+
+class Sig_Handler_2 : public Sig_Handler_1
+{
+public:
+ Sig_Handler_2 (ACE_Reactor &reactor, char *msg)
+ : Sig_Handler_1 (reactor, msg)
+ {
+ }
+
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *)
+ {
+ this->count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nsignal %S occurred in Sig_Handler_2 (%s, %d, %d) with count = %d",
+ signum, this->msg_, this->int_sigkey_, this->quit_sigkey_, this->count_));
+ if (this->count_ != 0 && signum == SIGQUIT)
+ {
+ if (this->reactor_.remove_handler (SIGQUIT, 0, 0,
+ this->quit_sigkey_) == -1)
+ ACE_ERROR ((LM_ERROR, "\n%p", "remove_handler"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "\nshutting down SIGQUIT in Sig_Handler_2 (%s, %d, %d)",
+ this->msg_, this->int_sigkey_, this->quit_sigkey_));
+ }
+ else
+ return 0;
+ }
+};
+
+static void
+external_handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG, "\nsignal %S occurred in external handler!", signum));
+}
+
+#if !defined (HPUX)
+int
+main (int argc, char *argv)
+{
+ // If argc > 1 then allow multiple handlers per-signal, else just
+ // allow 1 handler per-signal.
+ ACE_Sig_Handlers multi_handlers;
+
+ ACE_Reactor reactor (argc > 1 ? &multi_handlers: 0);
+
+ if (argc > 1)
+ {
+ // Register an "external" signal handler so that the
+ // ACE_Sig_Handlers code will have something to incorporate!
+ ACE_SignalHandler eh = ACE_SignalHandler (external_handler);
+ ACE_Sig_Action sa (eh);
+
+ sa.register_action (SIGINT);
+ }
+
+ // Create a bevy of handlers.
+ Sig_Handler_1 h1 (reactor, "howdy"), h2 (reactor, "doody");
+ Sig_Handler_2 h3 (reactor, "tutty"), h4 (reactor, "fruity");
+
+ // Wait for user to type SIGINT and SIGQUIT.
+
+ for (;;)
+ {
+ ACE_DEBUG ((LM_DEBUG, "\nwaiting for SIGINT or SIGQUIT\n"));
+ reactor.handle_events ();
+ }
+ return 0;
+}
+#else
+int
+main (void)
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "The HP C++ compiler is too lame to support this feature\n"), -1);
+}
+#endif /* HPUX */
diff --git a/examples/Reactor/Misc/test_time_value.cpp b/examples/Reactor/Misc/test_time_value.cpp
new file mode 100644
index 00000000000..691528eb292
--- /dev/null
+++ b/examples/Reactor/Misc/test_time_value.cpp
@@ -0,0 +1,69 @@
+#include "ace/ACE.h"
+// @(#)test_time_value.cpp 1.1 10/18/96
+
+
+inline int my_abs (int d) { return d > 0 ? d : -d; }
+
+ostream &
+operator<< (ostream &stream, const ACE_Time_Value &tv)
+{
+ if (tv.usec () < 0 || tv.sec () < 0)
+ stream << "-";
+
+ stream << dec << my_abs (int (tv.sec ())) << "."
+// << setw (6) << setfill ('0')
+ << dec << my_abs (int (tv.usec ()));
+ return stream;
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Time_Value tv1;
+ ACE_Time_Value tv2 (2);
+ ACE_Time_Value tv3 (100);
+ ACE_Time_Value tv4 (1, 1000000);
+ ACE_Time_Value tv5 (2);
+ ACE_Time_Value tv6 (1, -1000000);
+
+ ACE_ASSERT (tv1 == ACE_Time_Value (0));
+ ACE_ASSERT (tv2 < tv3);
+ ACE_ASSERT (tv2 <= tv2);
+ ACE_ASSERT (tv2 >= tv4);
+ ACE_ASSERT (tv5 >= tv6);
+ ACE_ASSERT (tv2 == ACE_Time_Value (1, 1000000));
+ ACE_ASSERT (tv5 == tv4);
+ ACE_ASSERT (tv2 == tv4);
+ ACE_ASSERT (tv1 != tv2);
+ ACE_ASSERT (tv6 == tv1);
+
+ cout << "0,0 :\t\t" << ACE_Time_Value (0,0) << endl;
+ cout << "-0,0 :\t\t" << ACE_Time_Value (-0,0) << endl;
+ cout << "0,-0 :\t\t" << ACE_Time_Value (0,-0) << endl;
+ cout << "-0,-0 :\t\t" << ACE_Time_Value (-0,-0) << endl;
+ cout << endl;
+
+ cout << "0,1 :\t\t" << ACE_Time_Value (0,1) << endl;
+ cout << "1,0 :\t\t" << ACE_Time_Value (1,0) << endl;
+ cout << "-1,0 :\t\t" << ACE_Time_Value (-1,0) << endl;
+ cout << "-1,-0 :\t\t" << ACE_Time_Value (-1,-0) << endl;
+ cout << endl;
+
+ cout << "1,1 :\t\t" << ACE_Time_Value (1,1) << endl;
+ cout << "-1,1 :\t\t" << ACE_Time_Value (-1,1) << endl;
+ cout << "1,-1 :\t\t" << ACE_Time_Value (1,-1) << endl;
+ cout << "-1,-1 :\t\t" << ACE_Time_Value (-1,-1) << endl;
+ cout << endl;
+
+ cout << "1,-1111111 :\t" << ACE_Time_Value (1,-1111111) << endl;
+ cout << "1,-100000 :\t" << ACE_Time_Value (1,-100000) << endl;
+ cout << "1,-1000000 :\t" << ACE_Time_Value (1,-1000000) << endl;
+ cout << "-1,1000000 :\t" << ACE_Time_Value (-1,1000000) << endl;
+ cout << "5,-1000000 :\t" << ACE_Time_Value (5,-1000000) << endl;
+ cout << "5,-1500000 :\t" << ACE_Time_Value (5,-1500000) << endl;
+ cout << "2,-2500000 :\t" << ACE_Time_Value (2,-2500000) << endl;
+ cout << "2,-4500000 :\t" << ACE_Time_Value (2,-4500000) << endl;
+
+ return 0;
+}
+
diff --git a/examples/Reactor/Misc/test_timer_queue.cpp b/examples/Reactor/Misc/test_timer_queue.cpp
new file mode 100644
index 00000000000..4e7010d1e94
--- /dev/null
+++ b/examples/Reactor/Misc/test_timer_queue.cpp
@@ -0,0 +1,47 @@
+#include "ace/Log_Msg.h"
+// @(#)test_timer_queue.cpp 1.1 10/18/96
+
+#include "ace/Timer_Queue.h"
+
+class Example_Handler : public ACE_Event_Handler
+{
+public:
+ Example_Handler (void)
+ : count_ (0)
+ {}
+
+ virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg)
+ {
+ ACE_DEBUG ((LM_DEBUG, "yow, the time has come and gone %d times %d, Horatio!\n",
+ this->count_++, int (arg)));
+ return 0;
+ }
+
+private:
+ int count_;
+};
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Timer_Queue tq;
+ Example_Handler eh;
+
+ ACE_ASSERT (tq.is_empty ());
+ ACE_ASSERT (ACE_Time_Value::zero == ACE_Time_Value (0));
+ int timer_id;
+
+ timer_id = tq.schedule (&eh, (const void *) 1, ACE_OS::gettimeofday ());
+ tq.schedule (&eh, (const void *) 2, ACE_OS::gettimeofday ());
+ tq.schedule (&eh, (const void *) 3, ACE_OS::gettimeofday ());
+ tq.cancel (timer_id);
+ ACE_ASSERT (!tq.is_empty ());
+ tq.expire (ACE_OS::gettimeofday ());
+ tq.schedule (&eh, (const void *) 4, ACE_OS::gettimeofday ());
+ tq.schedule (&eh, (const void *) 5, ACE_OS::gettimeofday ());
+ tq.cancel (&eh);
+ ACE_ASSERT (tq.is_empty ());
+ tq.expire (ACE_OS::gettimeofday ());
+ return 0;
+}
+
diff --git a/examples/Reactor/Multicast/Log_Wrapper.cpp b/examples/Reactor/Multicast/Log_Wrapper.cpp
new file mode 100644
index 00000000000..0b0526cdf2c
--- /dev/null
+++ b/examples/Reactor/Multicast/Log_Wrapper.cpp
@@ -0,0 +1,75 @@
+// client.C
+// @(#)Log_Wrapper.cpp 1.1 10/18/96
+
+
+#include "Log_Wrapper.h"
+
+Log_Wrapper::Log_Wrapper (void)
+{
+ this->log_msg_.sequence_number = 0;
+ this->log_msg_.app_id = ACE_OS::getpid();
+}
+
+Log_Wrapper::~Log_Wrapper (void)
+{
+}
+
+// Set the log_msg_ host address.
+// Get a binding to a logger object from orbixd
+
+int
+Log_Wrapper::open (const int port, const char *mcast_addr)
+{
+ struct hostent *host_info;
+ struct utsname host_data;
+
+ if (ACE_OS::uname (&host_data) < 0)
+ return -1;
+
+ if ((host_info = ACE_OS::gethostbyname (host_data.nodename)) == NULL)
+ return -1;
+ else
+ ACE_OS::memcpy ((char *) &this->log_msg_.host,
+ (char *) host_info->h_addr,
+ host_info->h_length);
+
+ // This starts out initialized to all zeros!
+ ACE_INET_Addr sockdg_addr;
+
+ if (this->logger_.open (sockdg_addr) == -1)
+ return -1;
+
+ if (this->server_.set (port, mcast_addr) == -1)
+ return -1;
+
+ // success.
+ return 0;
+}
+
+// Send the message to a logger object.
+// This wrapper fills in all the log_record info for you.
+// uses iovector stuff to make contiguous header and message.
+
+int
+Log_Wrapper::log_message (ACE_Log_Priority type, char *message)
+{
+ this->log_msg_.type = type; this->log_msg_.time = time (0);
+ this->log_msg_.msg_length = strlen(message);
+ this->log_msg_.sequence_number++;
+
+ iovec *iovp = new iovec[2];
+ iovp[0].iov_base = (char *) &log_msg_;
+ iovp[0].iov_len = sizeof log_msg_;
+ iovp[1].iov_base = message;
+ iovp[1].iov_len = log_msg_.msg_length;
+
+ logger_.send (iovp, 2, server_);
+
+ delete iovp;
+
+ // success.
+ return 0;
+}
+
+
+
diff --git a/examples/Reactor/Multicast/Log_Wrapper.h b/examples/Reactor/Multicast/Log_Wrapper.h
new file mode 100644
index 00000000000..d1932d92cfa
--- /dev/null
+++ b/examples/Reactor/Multicast/Log_Wrapper.h
@@ -0,0 +1,59 @@
+/* -*- C++ -*- */
+// @(#)Log_Wrapper.h 1.1 10/18/96
+
+
+// log_wrapper.h
+// wrapper around sending log messages via multicast
+
+#include "ace/Profile_Timer.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram.h"
+
+#if !defined (_LM_WRAPPER_H)
+#define _LM_WRAPPER_H
+
+class Log_Wrapper
+{
+public:
+ Log_Wrapper (void);
+ ~Log_Wrapper (void);
+
+ // = Types of logging messages.
+ enum ACE_Log_Priority
+ {
+ LM_MESSAGE,
+ LM_DEBUG,
+ LM_WARNING,
+ LM_ERROR,
+ LM_EMERG
+ };
+
+ int open (const int port, const char* mcast_addr);
+ // get an object reference from an orbixd
+
+ int log_message (ACE_Log_Priority type, char *message);
+ // send a string to the logger
+
+ // = Format of the logging record.
+ struct ACE_Log_Record
+ {
+ unsigned long sequence_number;
+ ACE_Log_Priority type;
+ long host;
+ long time;
+ long app_id;
+ long msg_length;
+ };
+
+private:
+ ACE_INET_Addr server_;
+ // Server address where records are logged.
+
+ ACE_Log_Record log_msg_;
+ // One record used for many log messages.
+
+ ACE_SOCK_Dgram logger_;
+ // A logger object.
+};
+
+#endif /* _LM_WRAPPER_H */
diff --git a/examples/Reactor/Multicast/Makefile b/examples/Reactor/Multicast/Makefile
new file mode 100644
index 00000000000..980cb7d28b3
--- /dev/null
+++ b/examples/Reactor/Multicast/Makefile
@@ -0,0 +1,69 @@
+#----------------------------------------------------------------------------
+# @(#)Makefile 1.1 10/18/96
+#
+# Makefile for the Reactor multicast tests
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+BIN = client server
+
+FILES = Log_Wrapper
+
+LSRC = $(addsuffix .cpp,$(FILES))
+LOBJ = $(addsuffix .o,$(FILES))
+SHOBJ = $(addsuffix .so,$(FILES))
+
+LDLIBS = $(addprefix .shobj/,$(SHOBJ))
+
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+
+BUILD = $(VBIN)
+
+#----------------------------------------------------------------------------
+# ACE stuff
+#----------------------------------------------------------------------------
+
+include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.lib.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.bin.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Dependencies
+#----------------------------------------------------------------------------
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+.obj/Log_Wrapper.o .shobj/Log_Wrapper.so: Log_Wrapper.cpp Log_Wrapper.h \
+ $(WRAPPER_ROOT)/ace/Profile_Timer.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram.i
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/examples/Reactor/Multicast/README b/examples/Reactor/Multicast/README
new file mode 100644
index 00000000000..85f64cc8120
--- /dev/null
+++ b/examples/Reactor/Multicast/README
@@ -0,0 +1,15 @@
+The following test illustrates the SOCK Mcast multicast wrappers in
+conjunction with the Reactor. This test was written by Tim Harrison
+(harrison@cs.wustl.edu).
+
+To run the server type:
+
+% server &
+
+It will wait for the first message sent to it and then read for 5 seconds.
+
+To run the client type any of these:
+
+% client -m max_message_size -i iterations
+% client < <filename>
+% client
diff --git a/examples/Reactor/Multicast/client.cpp b/examples/Reactor/Multicast/client.cpp
new file mode 100644
index 00000000000..1f5774fdb26
--- /dev/null
+++ b/examples/Reactor/Multicast/client.cpp
@@ -0,0 +1,110 @@
+// client.C (written by Tim Harrison)
+// @(#)client.cpp 1.1 10/18/96
+
+// This program reads in messages from stdin and sends them
+// to a Log_Wrapper.
+
+#include "ace/Log_Msg.h"
+#include "Log_Wrapper.h"
+
+const char *MCAST_ADDR = ACE_DEFAULT_MULTICAST_ADDR;
+
+// this is hardware specific.
+// use netstat(1M) to find whether your interface
+// is le0 or ie0
+
+const int UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+
+// maximum message size
+static int max_message_size = BUFSIZ * 20;
+
+// number of times to send message of max_message_size
+static int iterations = 0;
+
+static void
+parse_args (int argc, char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+ int c;
+
+ ACE_LOG_MSG->open (argv[0]);
+
+ while ((c = ACE_OS::getopt (argc, argv, "m:ui:")) != -1)
+ switch (c)
+ {
+ case 'm':
+ max_message_size = ACE_OS::atoi (optarg) * BUFSIZ;
+ break;
+ case 'i':
+ iterations = ACE_OS::atoi (optarg);
+ break;
+ case 'u':
+ // usage fallthrough
+ default:
+ ACE_ERROR ((LM_ERROR, "%n: -m max_message_size (in k) -i iterations\n%a", 1));
+ /* NOTREACHED */
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ int user_prompt;
+
+ parse_args (argc,argv);
+
+ ACE_DEBUG ((LM_DEBUG, "Max Buffer size = %d\n", max_message_size));
+
+ // Instantiate a log wrapper for logging
+ Log_Wrapper log;
+
+ // make a connection to a logger via orbixd
+ if (log.open (UDP_PORT, MCAST_ADDR) == -1)
+ ACE_OS::perror ("connect failed"), ACE_OS::exit (1);
+
+ char *buf = new char[::max_message_size];
+
+ // if -i has been specified, send max_message_size messages
+ // iterations number of times
+ if (iterations)
+ {
+ ACE_OS::memset (buf,1,::max_message_size);
+ while (iterations--)
+ if (log.log_message (Log_Wrapper::LM_DEBUG, buf) == -1)
+ perror("log failed."), exit(1);
+ }
+
+ // otherwise, a file has been redirected, or give prompts
+ else
+ {
+ // If a file has been redirected, don't activate user prompts
+ if (ACE_OS::isatty (0))
+ user_prompt = 1;
+ else
+ user_prompt = 0;
+
+ int nbytes;
+ // continually read messages from stdin and log them.
+ while (1)
+ {
+ if (user_prompt)
+ ACE_DEBUG ((LM_DEBUG, "\nEnter message ('Q':quit):\n"));
+
+ if ((nbytes = read (0, buf, max_message_size)) == 0)
+ break; // end of file
+ buf[nbytes] = '\0';
+
+ // quitting?
+ if (buf[0] == 'Q')
+ break;
+
+ // send the message to the logger
+ else if (log.log_message (Log_Wrapper::LM_DEBUG, buf) == -1)
+ perror("log failed."), exit(1);
+ } // while(1)
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "Client done.\n"));
+ return 0;
+}
diff --git a/examples/Reactor/Multicast/server.cpp b/examples/Reactor/Multicast/server.cpp
new file mode 100644
index 00000000000..b9c3942a9a7
--- /dev/null
+++ b/examples/Reactor/Multicast/server.cpp
@@ -0,0 +1,157 @@
+// server.C (written by Tim Harrison)
+// @(#)server.cpp 1.1 10/18/96
+
+//
+// listens to multicast address. after first message received, will
+// listen for 5 more seconds. prints Mbits/sec received from client.
+
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/Reactor.h"
+#include "Log_Wrapper.h"
+
+#if defined (ACE_HAS_IP_MULTICAST)
+class Server_Events : public ACE_Event_Handler
+{
+public:
+ Server_Events (u_short port,
+ const char *mcast_addr,
+ long time_interval = 0);
+ ~Server_Events (void);
+
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual ACE_HANDLE get_handle (void) const;
+
+ ACE_Time_Value *wait_time (void);
+
+private:
+ char *message_;
+ Log_Wrapper::ACE_Log_Record *log_record_;
+ char buf_[4*BUFSIZ];
+
+ int interval_;
+ // time interval to log messages
+
+ ACE_Time_Value *how_long_;
+ ACE_Reactor *reactor_;
+ ACE_SOCK_Dgram_Mcast mcast_dgram_;
+ ACE_INET_Addr remote_addr_;
+ ACE_INET_Addr mcast_addr_;
+
+ // = statistics on messages received
+ double total_bytes_received_;
+ int total_messages_received_;
+ int last_sequence_number_;
+};
+
+ACE_HANDLE
+Server_Events::get_handle (void) const
+{
+ return this->mcast_dgram_.get_handle ();
+}
+
+ACE_Time_Value *
+Server_Events::wait_time (void)
+{
+ return this->how_long_;
+}
+
+Server_Events::Server_Events (u_short port,
+ const char *mcast_addr,
+ long time_interval)
+ : total_bytes_received_ (0),
+ interval_ (time_interval),
+ mcast_addr_ (port, mcast_addr)
+{
+ // use ACE_SOCK_Dgram_Mcast factory to subscribe to multicast group.
+
+ if (this->mcast_dgram_.subscribe (this->mcast_addr_) == -1)
+ perror("can't subscribe to multicast group"), exit(1);
+
+ // Point to NULL so that we block in the beginning.
+ this->how_long_ = 0;
+
+ this->log_record_ = (Log_Wrapper::ACE_Log_Record *) &buf_;
+ this->message_ = &buf_[sizeof (Log_Wrapper::ACE_Log_Record)];
+}
+
+// A destructor that emacs refuses to color blue ;-)
+
+Server_Events::~Server_Events (void)
+{
+ this->mcast_dgram_.unsubscribe ();
+
+ ACE_DEBUG ((LM_DEBUG, "total bytes received = %d after %d second\n",
+ this->total_bytes_received_, this->interval_));
+
+ ACE_DEBUG ((LM_DEBUG, "Mbits/sec = %.2f\n",
+ (float) (total_bytes_received_ * 8 / (float) (1024*1024*interval_))));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "last sequence number = %d\ntotal messages received = %d\ndiff = %d\n",
+ this->last_sequence_number_,
+ this->total_messages_received_,
+ this->last_sequence_number_ - total_messages_received_));
+}
+
+int
+Server_Events::handle_input (ACE_HANDLE fd)
+{
+ // after the first message, point this to a timer
+ // that way, the next time reactor::handle_events is called,
+ // a nonzero time value will be passed in.
+ if (this->how_long_ == 0)
+ this->how_long_ = new ACE_Time_Value (this->interval_);
+
+ // receive message from multicast group
+ int retcode = this->mcast_dgram_.recv (this->buf_,
+ sizeof this->buf_,
+ this->remote_addr_);
+ if (retcode != -1)
+ {
+ total_messages_received_++;
+ total_bytes_received_ += retcode;
+ last_sequence_number_ = log_record_->sequence_number;
+ ACE_DEBUG ((LM_DEBUG, "sequence number = %d\n",
+ log_record_->sequence_number));
+ return 0;
+ }
+ else
+ return -1;
+}
+
+static const char MCAST_ADDR[] = ACE_DEFAULT_MULTICAST_ADDR;
+static const int UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+
+int
+main(int argc, char *argv[])
+{
+ int duration = 5;
+
+ // Instantiate a server which will receive messages for 5 seconds.
+ Server_Events server_events (UDP_PORT, MCAST_ADDR, duration);
+
+ // Instance of the ACE_Reactor.
+ ACE_Reactor reactor;
+
+ if (reactor.register_handler (&server_events,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "register_handler", 1));
+
+ for (;;)
+ reactor.handle_events (server_events.wait_time ());
+
+ /* NOTREACHED */
+ return 0;
+}
+#else
+int
+main (int argc, char *argv[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "error: %s must be run on a platform that support IP multicast\n",
+ argv[0]), -1);
+}
+#endif /* ACE_HAS_IP_MULTICAST */
diff --git a/examples/Reactor/Ntalker/Makefile b/examples/Reactor/Ntalker/Makefile
new file mode 100644
index 00000000000..d01010c27a0
--- /dev/null
+++ b/examples/Reactor/Ntalker/Makefile
@@ -0,0 +1,91 @@
+#----------------------------------------------------------------------------
+# @(#)Makefile 1.1 10/18/96
+#
+# Makefile for ntalker demo of SOCK_Dgram_Mcast
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+BIN = ntalker
+
+SRC = $(addsuffix .cpp,$(BIN))
+
+LDLIBS =
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+
+BUILD = $(VBIN)
+
+#----------------------------------------------------------------------------
+# ACE stuff
+#----------------------------------------------------------------------------
+
+include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.lib.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.bin.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Dependencies
+#----------------------------------------------------------------------------
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+.obj/ntalker.o .shobj/ntalker.so: ntalker.cpp \
+ $(WRAPPER_ROOT)/ace/INET_Addr.h \
+ $(WRAPPER_ROOT)/ace/ACE.h \
+ $(WRAPPER_ROOT)/ace/OS.h \
+ $(WRAPPER_ROOT)/ace/Time_Value.h \
+ $(WRAPPER_ROOT)/ace/config.h \
+ $(WRAPPER_ROOT)/ace/Trace.h \
+ $(WRAPPER_ROOT)/ace/ACE.i \
+ $(WRAPPER_ROOT)/ace/Log_Msg.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.h \
+ $(WRAPPER_ROOT)/ace/Log_Priority.h \
+ $(WRAPPER_ROOT)/ace/Log_Record.i \
+ $(WRAPPER_ROOT)/ace/Addr.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram_Mcast.h \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \
+ $(WRAPPER_ROOT)/ace/SOCK.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.h \
+ $(WRAPPER_ROOT)/ace/IPC_SAP.i \
+ $(WRAPPER_ROOT)/ace/SOCK.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Dgram_Mcast.i \
+ $(WRAPPER_ROOT)/ace/Reactor.h \
+ $(WRAPPER_ROOT)/ace/Handle_Set.h \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.h \
+ $(WRAPPER_ROOT)/ace/Event_Handler.h \
+ $(WRAPPER_ROOT)/ace/Synch.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(WRAPPER_ROOT)/ace/Synch_T.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.cpp \
+ $(WRAPPER_ROOT)/ace/Thread.h \
+ $(WRAPPER_ROOT)/ace/Synch_T.i \
+ $(WRAPPER_ROOT)/ace/Timer_Queue.i \
+ $(WRAPPER_ROOT)/ace/Signal.h \
+ $(WRAPPER_ROOT)/ace/Set.h \
+ $(WRAPPER_ROOT)/ace/Set.cpp \
+ $(WRAPPER_ROOT)/ace/Set.i \
+ $(WRAPPER_ROOT)/ace/Token.h \
+ $(WRAPPER_ROOT)/ace/Pipe.h \
+ $(WRAPPER_ROOT)/ace/Pipe.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.h \
+ $(WRAPPER_ROOT)/ace/SOCK_IO.i \
+ $(WRAPPER_ROOT)/ace/SOCK_Stream.i \
+ $(WRAPPER_ROOT)/ace/Reactor.i
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/examples/Reactor/Ntalker/ntalker.cpp b/examples/Reactor/Ntalker/ntalker.cpp
new file mode 100644
index 00000000000..54c8e20f453
--- /dev/null
+++ b/examples/Reactor/Ntalker/ntalker.cpp
@@ -0,0 +1,188 @@
+// Server.C
+// @(#)ntalker.cpp 1.1 10/18/96
+
+//
+// listens to multicast address. after first message received, will
+// listen for 5 more seconds. prints Mbits/sec received from client
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/Reactor.h"
+
+#if defined (ACE_HAS_IP_MULTICAST)
+// network interface to subscribe to
+// this is hardware specific.
+// use netstat(1M) to find whether your interface
+// is le0 or ie0
+
+static const char *interface = "le0";
+static const char *MCAST_ADDR = ACE_DEFAULT_MULTICAST_ADDR;
+static const u_short UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+
+// Handle both multicast and stdin events.
+
+class Handle_Events : public ACE_Event_Handler
+{
+public:
+ Handle_Events (u_short udp_port,
+ const char *ip_addr,
+ const char *interface,
+ ACE_Reactor &reactor);
+ ~Handle_Events (void);
+
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+
+private:
+ ACE_SOCK_Dgram_Mcast mcast_;
+ ACE_Handle_Set handle_set_;
+};
+
+int
+Handle_Events::handle_input (ACE_HANDLE h)
+{
+ char buf[BUFSIZ];
+
+ if (h == 0)
+ {
+ int readresult = ACE_OS::read (h, buf, BUFSIZ);
+ if (readresult > 0)
+ {
+ if (this->mcast_.send (buf, readresult) != readresult)
+ {
+ ACE_OS::perror ("send error");
+ return -1;
+ }
+ return 0;
+ }
+ else if (readresult == -1)
+ ::perror ("can't read from STDIN");
+
+ return -1;
+ }
+ else
+ {
+ ACE_INET_Addr remote_addr;
+
+ // receive message from multicast group
+ int retcode = this->mcast_.recv (buf, sizeof buf, remote_addr);
+
+ if (retcode != -1)
+ {
+ cout << "received datagram from host " << remote_addr.get_host_name ()
+ << " on port " << remote_addr.get_port_number ()
+ << " bytes = " << retcode << endl;
+ ACE_OS::write (ACE_STDOUT, buf, retcode);
+ cout << endl;
+ return 0;
+ }
+
+ ACE_OS::perror ("Something amiss.");
+ return -1;
+ }
+}
+
+int
+Handle_Events::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
+{
+ if (h == 0)
+ cout << "STDIN_Events handle removed from reactor." << endl << flush;
+ else
+ cout << "Mcast_Events handle removed from reactor." << endl << flush;
+ return 0;
+}
+
+Handle_Events::~Handle_Events (void)
+{
+ // ACE_OS::exit on error (bogus)...
+
+ if (this->mcast_.unsubscribe () == -1)
+ ACE_OS::perror ("unsubscribe fails"), ACE_OS::exit (1);
+}
+
+Handle_Events::Handle_Events (u_short udp_port,
+ const char *ip_addr,
+ const char *interface,
+ ACE_Reactor &reactor)
+{
+ // Create multicast address to listen on.
+
+ ACE_INET_Addr sockmc_addr (udp_port, ip_addr);
+
+ // subscribe to multicast group.
+
+ if (this->mcast_.subscribe (sockmc_addr, 1, interface) == -1)
+ ACE_OS::perror ("can't subscribe to multicast group"), ACE_OS::exit (1);
+
+ // disable loopbacks
+
+// if (this->mcast_.set_option (IP_MULTICAST_LOOP, 0) == -1 )
+// ACE_OS::perror (" can't disable loopbacks " ), ACE_OS::exit (1);
+
+ this->handle_set_.set_bit (0);
+ this->handle_set_.set_bit (this->mcast_.get_handle ());
+
+ // Register callbacks with the ACE_Reactor.
+ if (reactor.register_handler (this->handle_set_,
+ this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_OS::perror ("can't register events"), ACE_OS::exit (1);
+}
+
+static void
+parse_args (int argc, char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+ int c;
+
+ while ((c = ACE_OS::getopt (argc, argv, "i:u")) != -1)
+ switch (c)
+ {
+ case 'i':
+ interface = optarg;
+ break;
+ case 'u':
+ // usage fallthrough
+ default:
+ cerr << argv[0] << " -i interface\n";
+ ::exit (1);
+ }
+}
+
+static sig_atomic_t done = 0;
+
+// Signal handler.
+
+static void
+handler (int)
+{
+ done = 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Sig_Action sig ((ACE_SignalHandler) handler, SIGINT);
+ parse_args (argc, argv);
+
+ ACE_Reactor reactor;
+ Handle_Events handle_events (UDP_PORT, MCAST_ADDR, interface, reactor);
+
+ // main loop
+
+ while (!done)
+ reactor.handle_events ();
+
+ cout << "\ntalker Done.\n";
+ return 0;
+}
+#else
+int
+main (int argc, char *argv[])
+{
+ ACE_ERROR ((LM_ERROR, "error: %s must be run on a platform that support IP multicast\n",
+ argv[0]));
+ return 0;
+}
+#endif /* ACE_HAS_IP_MULTICAST */
diff --git a/examples/Reactor/README b/examples/Reactor/README
new file mode 100644
index 00000000000..fefaeeaf317
--- /dev/null
+++ b/examples/Reactor/README
@@ -0,0 +1,20 @@
+This directory contains subdirectories that test the ACE Reactor and Proactor
+
+ . Dgram
+ Tests the CODgram and Dgram classes with the Reactor.
+
+ . Misc
+ Various miscellaneous tests of Reactor functionality
+ (e.g., signals, timers, notification, etc.).
+
+ . Multicast
+ Tests out the ACE multicast capabilities in conjunction
+ with the Reactor.
+
+ . Ntalker
+ A program that implements a multicast "chat" program.
+
+
+ . Proactor
+ A program that illustrates the "Proactive" version of
+ the Reactor
diff --git a/examples/Reactor/ReactorEx/README b/examples/Reactor/ReactorEx/README
new file mode 100644
index 00000000000..1184d09dd68
--- /dev/null
+++ b/examples/Reactor/ReactorEx/README
@@ -0,0 +1,204 @@
+The ACE_ReactorEx encapsulates the Win32 WaitForMultipleObjects() API
+within ACE. The ACE_ReactorEx is similar in spirit to the
+ACE_Reactor, except that (1) it is much simpler and (2) it works for
+the complete range of Win32 handles (whereas the ACE_Reactor just
+works for socket handles.
+
+Here's the API for the ACE_ReactorEx:
+
+class ACE_ReactorEx
+{
+public:
+ // = Event loop.
+ virtual int handle_events (ACE_Time_Value *);
+
+ // = Handler registration management.
+ virtual int register_handler (ACE_Event_Handler *);
+ virtual int remove_handler (ACE_Event_Handler *);
+
+ virtual int notify (void);
+
+ // = Timer management
+ virtual int schedule_timer (), etc.
+ // ...
+};
+
+----------------------------------------
+
+Here's how you might use it:
+
+----------------------------------------
+
+class My_Thread_Handler : public ACE_Event_Handler
+{
+public:
+ My_Thread_Handler (void) {
+ // Create a thread that will run
+ // for a time and then exit.
+ this->thread_handle_ =
+ ACE_OS::thr_create (run, ......);
+ }
+
+ // Called back by the ACE_ReactorEx when the
+ // event is signaled.
+ virtual int handle_signal (int)
+ {
+ cout << "thread is done" << endl;
+ }
+
+ virtual ACE_HANDLE get_handle (void) const
+ {
+ return this->thread_handle_;
+ }
+
+private:
+ ACE_HANDLE thread_handle_;
+
+ static void *run (void *) {
+ // Sleep for a while and then exit.
+ ACE_OS::sleep (100000);
+ return 0;
+ }
+};
+
+----------------------------------------
+
+The main program might look something like this:
+
+----------------------------------------
+
+int main (void)
+{
+ // ...
+ ACE_ReactorEx dispatcher;
+ My_Thread_Handler handler;
+
+ // Register the thread handler.
+ dispatcher.register_handler (&handler);
+
+ // Block until the thread exits and the
+ // handle_signal() method of the My_Thread_Handler
+ // is called!
+ dispatcher.handle_events ();
+
+ // ...
+}
+
+----------------------------------------
+
+. test_remove_handler --
+
+This application tests the ReactorEx's ability to handle simultaneous
+events. If you pass anything on the command-line, then each handler
+requests to be removed from the ReactorEx after each event. This has
+a funky effect on the order in which handlers are serviced. So, if no
+parameters are passed in, the handlers should be serviced 1 through
+MAXIMUM_WAIT_OBJECTS. If handlers to request to be removed as signals
+occur, they will be serviced 1, MAX, MAX-1, ..., 2. This is because
+of a ReactorEx bookkeeping optimization.
+
+. test_reactorEx.cpp --
+
+This test application tests a wide range of events that can be
+demultiplexed using various ACE utilities. Events used include ^C
+events, reading from STDIN, vanilla Win32 events, thread exits,
+ReactorEx notifications, proactive reads, and proactive writes.
+
+The proactive I/O events are demultiplexed by the ACE_Proactor. The
+thread exits, notications, and vanilla Win32 events are demultiplexed
+by the ACE_ReactorEx. To enable a single thread to run all these
+events, the Proactor is integrated with the ReactorEx.
+
+The test application prototypes a simple ntalk program. Two instances
+of the application connect. Input from either console is displayed on
+the others console also. Because of the evils of Win32 STDIN, a
+separate thread is used to read from STDIN. To test the Proactor and
+ReactorEx, I/O between the remote processes is performed proactively
+and interactions between the STDIN thread and the main thread are
+performed reactively.
+
+The following description of the test application is in two parts.
+The participants section explains the main components involved in the
+application. The collaboration section describes how the partipants
+interact in response to the multiple event types which occur.
+
+The ReactorEx test application has the following participants:
+
+. ReactorEx -- The ReactorEx demultiplexes Win32 "waitable" events
+ using WaitForMultipleObjects.
+
+. Proactor -- The proactor initiates and demultiplexes overlapped I/O
+ operations. The Proactor registers with the ReactorEx so that a
+ single-thread can demultiplex all application events.
+
+. STDIN_Handler -- STDIN_Handler is an Active Object which reads from
+ STDIN and forwards the input to the Peer_Handler. This runs
+ in a separate thread to make the test more interesting. However,
+ STDIN is "waitable", so in general it can be waited on by the ACE
+ ReactorEx, thanks MicroSlush!
+
+. Peer_Handler -- The Peer_Handler connects to another instance of
+ test_reactorEx. It Proactively reads and writes data to the peer.
+ When the STDIN_Handler gives it messages, it fowards them to the
+ remote peer. When it receives messages from the remote peer, it
+ prints the output to the console.
+
+The collaborations of the participants are as follows:
+
+. Initialization
+
+ Peer_Handler -- connects to the remote peer. It then begins
+ proactively reading from the remote connection. Note that it will
+ be notified by the Proactor when a read completes. It also
+ registers a new_msg_event with the ReactorEx. Note that when the
+ new_msg_event is signaled (by the STDIN_Handler),
+ Peer_Handler::handle_signal will get called.
+
+ STDIN_Handler -- STDIN_Handler registers a signal handler for
+ SIGINT. This just captures the exception so that the kernel doesn't
+ kill our process; We want to exit gracefully. It also creates an
+ Exit_Hook object which registers the STDIN_Handler's thread handle
+ with the ReactorEx. The Exit_Hook will get called back when the
+ STDIN_Handler thread exits. After registering these, it blocks
+ reading from STDIN.
+
+ Proactor -- is registered with the ReactorEx.
+
+ The main thread of control waits in the ReactorEx.
+
+. STDIN events -- When the STDIN_Handler thread reads from STDIN, it
+ puts the message on Peer_Handler's message queue and signals the
+ new_msg_event. It then returns to reading from STDIN.
+
+. new_msg_events -- The ReactorEx thread wakes up and calls
+ Peer_Handler::handle_signal. The Peer_Handler then tries to dequeue
+ a message from its message queue. If it can, the message is
+ Proactively sent to the remote peer. Note that the Peer_Handler
+ will be notified with this operation is complete. The Peer_Handler
+ then falls back into the ReactorEx event loop.
+
+. Send complete event -- When a proactive send is complete, the
+ Proactor is notified by the ReactorEx. The Proactor, in turn,
+ notifies the Peer_Handler. The Peer_Handler then checks for more
+ messages from the message queue. If there are any, it tries to send
+ them. If there are not, it returns to the ReactorEx event loop.
+ This is ok since it is notified via new_msg_event when new message
+ arrive.
+
+. Read complete event -- When a proactive read is complete (the
+ Peer_Handler initiated a proactive read when it connected to the
+ remote peer), the Proactor is notified by the ReactorEx. The
+ Proactor, in turn notifies the Peer_Handler. If the read was
+ successful the Peer_Handler just displays the received msg to the
+ console and reinvokes a proactive read from the network connection.
+ If the read failed (i.e. the remote peer exited), the Peer_Handler
+ sets a flag to end the event loop and returns. This will cause the
+ application to exit.
+
+. ^C events -- When the user types ^C at the console, the
+ STDIN_Handler's signal handler will be called. It does nothing, but
+ as a result of the signal, the STDIN_Handler thread will exit.
+
+. STDIN_Handler thread exits -- The Exit_Hook will get called back
+ from the ReactorEx. Exit_Hook::handle_signal sets a flag to end the
+ event loop and returns. This will cause the application to exit.
diff --git a/examples/Reactor/ReactorEx/reactorex.mak b/examples/Reactor/ReactorEx/reactorex.mak
new file mode 100644
index 00000000000..150d04508d7
--- /dev/null
+++ b/examples/Reactor/ReactorEx/reactorex.mak
@@ -0,0 +1,535 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+!IF "$(CFG)" == ""
+CFG=test_remove_handler - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to test_remove_handler - Win32\
+ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ntalk - Win32 Release" && "$(CFG)" != "ntalk - Win32 Debug" &&\
+ "$(CFG)" != "test_remove_handler - Win32 Release" && "$(CFG)" !=\
+ "test_remove_handler - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "reactorEx.mak" CFG="test_remove_handler - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ntalk - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "ntalk - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "test_remove_handler - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "test_remove_handler - Win32 Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "ntalk - Win32 Debug"
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ntalk - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ntalk\Release"
+# PROP BASE Intermediate_Dir "ntalk\Release"
+# PROP BASE Target_Dir "ntalk"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ntalk\Release"
+# PROP Intermediate_Dir "ntalk\Release"
+# PROP Target_Dir "ntalk"
+OUTDIR=.\ntalk\Release
+INTDIR=.\ntalk\Release
+
+ALL : "$(OUTDIR)\ntalk.exe"
+
+CLEAN :
+ -@erase ".\ntalk\Release\ntalk.exe"
+ -@erase ".\ntalk\Release\test_reactorEx.obj"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/ntalk.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\ntalk\Release/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntalk.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ace.lib /nologo /subsystem:console /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib ace.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)/ntalk.pdb" /machine:I386 /out:"$(OUTDIR)/ntalk.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_reactorEx.obj"
+
+"$(OUTDIR)\ntalk.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "ntalk - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ntalk\Debug"
+# PROP BASE Intermediate_Dir "ntalk\Debug"
+# PROP BASE Target_Dir "ntalk"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir "ntalk"
+OUTDIR=.
+INTDIR=.\debug
+
+ALL : "$(OUTDIR)\test_reactorEx.exe"
+
+CLEAN :
+ -@erase ".\debug\vc40.pdb"
+ -@erase ".\debug\vc40.idb"
+ -@erase ".\test_reactorEx.exe"
+ -@erase ".\debug\test_reactorEx.obj"
+ -@erase ".\test_reactorEx.ilk"
+ -@erase ".\test_reactorEx.pdb"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/ntalk.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\debug/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntalk.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ace.lib /nologo /subsystem:console /debug /machine:I386 /out:"test_reactorEx.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib ace.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)/test_reactorEx.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/test_reactorEx.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_reactorEx.obj"
+
+"$(OUTDIR)\test_reactorEx.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "test_remove_handler - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "test_remove_handler\Release"
+# PROP BASE Intermediate_Dir "test_remove_handler\Release"
+# PROP BASE Target_Dir "test_remove_handler"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "test_remove_handler\Release"
+# PROP Intermediate_Dir "test_remove_handler\Release"
+# PROP Target_Dir "test_remove_handler"
+OUTDIR=.\test_remove_handler\Release
+INTDIR=.\test_remove_handler\Release
+
+ALL : "$(OUTDIR)\test_remove_handler.exe"
+
+CLEAN :
+ -@erase ".\test_remove_handler\Release\test_remove_handler.exe"
+ -@erase ".\test_remove_handler\Release\test_remove_handler.obj"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/test_remove_handler.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\test_remove_handler\Release/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_remove_handler.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)/test_remove_handler.pdb" /machine:I386\
+ /out:"$(OUTDIR)/test_remove_handler.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_remove_handler.obj"
+
+"$(OUTDIR)\test_remove_handler.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "test_remove_handler - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "test_remove_handler\Debug"
+# PROP BASE Intermediate_Dir "test_remove_handler\Debug"
+# PROP BASE Target_Dir "test_remove_handler"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir "test_remove_handler"
+OUTDIR=.
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\test_remove_handler.exe"
+
+CLEAN :
+ -@erase ".\debug\vc40.pdb"
+ -@erase ".\debug\vc40.idb"
+ -@erase ".\test_remove_handler.exe"
+ -@erase ".\Debug\test_remove_handler.obj"
+ -@erase ".\test_remove_handler.ilk"
+ -@erase ".\test_remove_handler.pdb"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/test_remove_handler.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_remove_handler.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ace.lib /nologo /subsystem:console /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib ace.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)/test_remove_handler.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/test_remove_handler.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_remove_handler.obj"
+
+"$(OUTDIR)\test_remove_handler.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "ntalk - Win32 Release"
+# Name "ntalk - Win32 Debug"
+
+!IF "$(CFG)" == "ntalk - Win32 Release"
+
+!ELSEIF "$(CFG)" == "ntalk - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\test_reactorEx.cpp
+DEP_CPP_TEST_=\
+ {$(INCLUDE)}"\ace\ReactorEx.h"\
+ {$(INCLUDE)}"\ace\Proactor.h"\
+ {$(INCLUDE)}"\ace\SOCK_Connector.h"\
+ {$(INCLUDE)}"\ace\SOCK_Acceptor.h"\
+ {$(INCLUDE)}"\ace\Get_Opt.h"\
+ {$(INCLUDE)}"\ace\Time_Value.h"\
+ {$(INCLUDE)}"\ace\Service_Config.h"\
+ {$(INCLUDE)}"\ace\Synch.h"\
+ {$(INCLUDE)}"\ace\Task.h"\
+ {$(INCLUDE)}"\ace\OS.h"\
+ {$(INCLUDE)}"\ace\Timer_Queue.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.h"\
+ {$(INCLUDE)}"\ace\Token.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.h"\
+ {$(INCLUDE)}"\ace\ReactorEx.i"\
+ {$(INCLUDE)}"\ace\Timer_Queue.i"\
+ {$(INCLUDE)}"\ace\ACE.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.i"\
+ {$(INCLUDE)}"\ace\ACE.i"\
+ {$(INCLUDE)}"\ace\Log_Msg.h"\
+ {$(INCLUDE)}"\ace\Log_Record.h"\
+ {$(INCLUDE)}"\ace\Log_Priority.h"\
+ {$(INCLUDE)}"\ace\Log_Record.i"\
+ {$(INCLUDE)}"\ace\Token.i"\
+ {$(INCLUDE)}"\ace\Stack.h"\
+ {$(INCLUDE)}"\ace\Synch_Options.h"\
+ {$(INCLUDE)}"\ace\Map_Manager.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.i"\
+ {$(INCLUDE)}"\ace\Stack.i"\
+ {$(INCLUDE)}"\ace\Stack.cpp"\
+ {$(INCLUDE)}"\ace\Map_Manager.i"\
+ {$(INCLUDE)}"\ace\Map_Manager.cpp"\
+ {$(INCLUDE)}"\ace\Malloc.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.h"\
+ {$(INCLUDE)}"\ace\Malloc.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.i"\
+ {$(INCLUDE)}"\ace\Trace.h"\
+ {$(INCLUDE)}"\ace\Malloc_T.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.cpp"\
+ {$(INCLUDE)}"\ace\Signal.h"\
+ {$(INCLUDE)}"\ace\Mem_Map.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.i"\
+ {$(INCLUDE)}"\ace\Set.h"\
+ {$(INCLUDE)}"\ace\Signal.i"\
+ {$(INCLUDE)}"\ace\Set.i"\
+ {$(INCLUDE)}"\ace\Set.cpp"\
+ {$(INCLUDE)}"\ace\Mem_Map.i"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.i"\
+ {$(INCLUDE)}"\ace\Message_Block.h"\
+ {$(INCLUDE)}"\ace\Proactor.i"\
+ {$(INCLUDE)}"\ace\Message_Block.i"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.h"\
+ {$(INCLUDE)}"\ace\SOCK_Connector.i"\
+ {$(INCLUDE)}"\ace\SOCK_IO.h"\
+ {$(INCLUDE)}"\ace\INET_Addr.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.i"\
+ {$(INCLUDE)}"\ace\SOCK.h"\
+ {$(INCLUDE)}"\ace\SOCK_IO.i"\
+ {$(INCLUDE)}"\ace\Addr.h"\
+ {$(INCLUDE)}"\ace\IPC_SAP.h"\
+ {$(INCLUDE)}"\ace\SOCK.i"\
+ {$(INCLUDE)}"\ace\Addr.i"\
+ {$(INCLUDE)}"\ace\IPC_SAP.i"\
+ {$(INCLUDE)}"\ace\INET_Addr.i"\
+ {$(INCLUDE)}"\ace\SOCK_Acceptor.i"\
+ {$(INCLUDE)}"\ace\Get_Opt.i"\
+ {$(INCLUDE)}"\ace\config.h"\
+ {$(INCLUDE)}"\ace\Time_Value.i"\
+ {$(INCLUDE)}"\ace\Service_Object.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.h"\
+ {$(INCLUDE)}"\ace\Service_Config.i"\
+ {$(INCLUDE)}"\ace\Reactor.h"\
+ {$(INCLUDE)}"\ace\Svc_Conf_Tokens.h"\
+ {$(INCLUDE)}"\ace\Shared_Object.h"\
+ {$(INCLUDE)}"\ace\Service_Object.i"\
+ {$(INCLUDE)}"\ace\Shared_Object.i"\
+ {$(INCLUDE)}"\ace\Thread.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.i"\
+ {$(INCLUDE)}"\ace\Thread.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.h"\
+ {$(INCLUDE)}"\ace\Pipe.h"\
+ {$(INCLUDE)}"\ace\Reactor.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.i"\
+ {$(INCLUDE)}"\ace\Pipe.i"\
+ {$(INCLUDE)}"\ace\Synch.i"\
+ {$(INCLUDE)}"\ace\Synch_T.h"\
+ {$(INCLUDE)}"\ace\Synch_T.i"\
+ {$(INCLUDE)}"\ace\Synch_T.cpp"\
+ {$(INCLUDE)}"\ace\Message_Queue.h"\
+ {$(INCLUDE)}"\ace\Task.i"\
+ {$(INCLUDE)}"\ace\Task.cpp"\
+ {$(INCLUDE)}"\ace\IO_Cntl_Msg.h"\
+ {$(INCLUDE)}"\ace\Message_Queue.i"\
+ {$(INCLUDE)}"\ace\Message_Queue.cpp"\
+ {$(INCLUDE)}"\ace\Module.h"\
+ {$(INCLUDE)}"\ace\Module.i"\
+ {$(INCLUDE)}"\ace\Module.cpp"\
+ {$(INCLUDE)}"\ace\Stream_Modules.h"\
+ {$(INCLUDE)}"\ace\Stream_Modules.i"\
+ {$(INCLUDE)}"\ace\Stream_Modules.cpp"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TIMEB.H"\
+ {$(INCLUDE)}"\ace\OS.i"\
+
+NODEP_CPP_TEST_=\
+ ".\..\..\ace\ace\Sync_T.h"\
+ ".\..\..\ace\semLib.h"\
+
+
+"$(INTDIR)\test_reactorEx.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "test_remove_handler - Win32 Release"
+# Name "test_remove_handler - Win32 Debug"
+
+!IF "$(CFG)" == "test_remove_handler - Win32 Release"
+
+!ELSEIF "$(CFG)" == "test_remove_handler - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\test_remove_handler.cpp
+DEP_CPP_TEST_R=\
+ {$(INCLUDE)}"\ace\ReactorEx.h"\
+ {$(INCLUDE)}"\ace\Service_Config.h"\
+ {$(INCLUDE)}"\ace\Synch.h"\
+ {$(INCLUDE)}"\ace\Timer_Queue.h"\
+ {$(INCLUDE)}"\ace\Time_Value.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.h"\
+ {$(INCLUDE)}"\ace\Token.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.h"\
+ {$(INCLUDE)}"\ace\ReactorEx.i"\
+ {$(INCLUDE)}"\ace\Timer_Queue.i"\
+ {$(INCLUDE)}"\ace\config.h"\
+ {$(INCLUDE)}"\ace\Time_Value.i"\
+ {$(INCLUDE)}"\ace\Trace.h"\
+ {$(INCLUDE)}"\ace\ACE.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.i"\
+ {$(INCLUDE)}"\ace\OS.h"\
+ {$(INCLUDE)}"\ace\ACE.i"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TIMEB.H"\
+ {$(INCLUDE)}"\ace\OS.i"\
+ {$(INCLUDE)}"\ace\Log_Msg.h"\
+ {$(INCLUDE)}"\ace\Log_Record.h"\
+ {$(INCLUDE)}"\ace\Log_Priority.h"\
+ {$(INCLUDE)}"\ace\Log_Record.i"\
+ {$(INCLUDE)}"\ace\Token.i"\
+ {$(INCLUDE)}"\ace\Stack.h"\
+ {$(INCLUDE)}"\ace\Synch_Options.h"\
+ {$(INCLUDE)}"\ace\Map_Manager.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.i"\
+ {$(INCLUDE)}"\ace\Stack.i"\
+ {$(INCLUDE)}"\ace\Stack.cpp"\
+ {$(INCLUDE)}"\ace\Map_Manager.i"\
+ {$(INCLUDE)}"\ace\Map_Manager.cpp"\
+ {$(INCLUDE)}"\ace\Malloc.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.h"\
+ {$(INCLUDE)}"\ace\Malloc.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.cpp"\
+ {$(INCLUDE)}"\ace\Signal.h"\
+ {$(INCLUDE)}"\ace\Mem_Map.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.i"\
+ {$(INCLUDE)}"\ace\Set.h"\
+ {$(INCLUDE)}"\ace\Signal.i"\
+ {$(INCLUDE)}"\ace\Set.i"\
+ {$(INCLUDE)}"\ace\Set.cpp"\
+ {$(INCLUDE)}"\ace\Mem_Map.i"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.i"\
+ {$(INCLUDE)}"\ace\Service_Object.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.h"\
+ {$(INCLUDE)}"\ace\Proactor.h"\
+ {$(INCLUDE)}"\ace\Service_Config.i"\
+ {$(INCLUDE)}"\ace\Reactor.h"\
+ {$(INCLUDE)}"\ace\Svc_Conf_Tokens.h"\
+ {$(INCLUDE)}"\ace\Shared_Object.h"\
+ {$(INCLUDE)}"\ace\Service_Object.i"\
+ {$(INCLUDE)}"\ace\Shared_Object.i"\
+ {$(INCLUDE)}"\ace\Thread.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.i"\
+ {$(INCLUDE)}"\ace\Thread.i"\
+ {$(INCLUDE)}"\ace\Message_Block.h"\
+ {$(INCLUDE)}"\ace\Proactor.i"\
+ {$(INCLUDE)}"\ace\Message_Block.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.h"\
+ {$(INCLUDE)}"\ace\Pipe.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.h"\
+ {$(INCLUDE)}"\ace\Reactor.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.i"\
+ {$(INCLUDE)}"\ace\Pipe.i"\
+ {$(INCLUDE)}"\ace\SOCK_IO.h"\
+ {$(INCLUDE)}"\ace\INET_Addr.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.i"\
+ {$(INCLUDE)}"\ace\SOCK.h"\
+ {$(INCLUDE)}"\ace\SOCK_IO.i"\
+ {$(INCLUDE)}"\ace\Addr.h"\
+ {$(INCLUDE)}"\ace\IPC_SAP.h"\
+ {$(INCLUDE)}"\ace\SOCK.i"\
+ {$(INCLUDE)}"\ace\Addr.i"\
+ {$(INCLUDE)}"\ace\IPC_SAP.i"\
+ {$(INCLUDE)}"\ace\INET_Addr.i"\
+ {$(INCLUDE)}"\ace\Synch.i"\
+ {$(INCLUDE)}"\ace\Synch_T.h"\
+ {$(INCLUDE)}"\ace\Synch_T.i"\
+ {$(INCLUDE)}"\ace\Synch_T.cpp"\
+
+NODEP_CPP_TEST_R=\
+ ".\..\..\ace\semLib.h"\
+ ".\..\..\ace\ace\Sync_T.h"\
+
+
+"$(INTDIR)\test_remove_handler.obj" : $(SOURCE) $(DEP_CPP_TEST_R) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/examples/Reactor/ReactorEx/reactorex.mdp b/examples/Reactor/ReactorEx/reactorex.mdp
new file mode 100644
index 00000000000..0135cc67b75
--- /dev/null
+++ b/examples/Reactor/ReactorEx/reactorex.mdp
Binary files differ
diff --git a/examples/Reactor/ReactorEx/test_reactorEx.cpp b/examples/Reactor/ReactorEx/test_reactorEx.cpp
new file mode 100644
index 00000000000..757e78c1e9e
--- /dev/null
+++ b/examples/Reactor/ReactorEx/test_reactorEx.cpp
@@ -0,0 +1,444 @@
+// ============================================================================
+// @(#)test_reactorEx.cpp 1.1 10/18/96
+
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_reactorEx.cpp
+//
+// = DESCRIPTION
+// This test application tests a wide range of events that can be
+// demultiplexed using various ACE utilities. Events used include ^C
+// events, reading from STDIN, vanilla Win32 events, thread exits,
+// ReactorEx notifications, proactive reads, and proactive writes.
+//
+// The proactive I/O events are demultiplexed by the ACE_Proactor.
+// The thread exits, notications, and vanilla Win32 events are
+// demultiplexed by the ACE_ReactorEx. To enable a single thread
+// to run all these events, the Proactor is integrated with the
+// ReactorEx.
+//
+// = AUTHOR
+// Tim Harrison
+//
+// ============================================================================
+
+#include "ace/ReactorEx.h"
+#include "ace/Proactor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Get_Opt.h"
+#include "ace/Time_Value.h"
+#include "ace/Service_Config.h"
+#include "ace/Synch.h"
+#include "ace/Task.h"
+#include "ace/OS.h"
+
+typedef ACE_Task<ACE_MT_SYNCH> MT_TASK;
+
+class Peer_Handler : public MT_TASK
+ // = TITLE
+ // Connect to a server. Receive messages from STDIN_Handler
+ // and forward them to the server using proactive I/O.
+{
+public:
+ Peer_Handler (int argc, char *argv[]);
+
+ int open (void * =0);
+ // This method creates the network connection to the remote peer.
+ // It does blocking connects and accepts depending on whether a
+ // hostname was specified from the command line.
+
+ virtual int handle_output_complete (ACE_Message_Block *msg,
+ long bytes_transfered);
+ // One of our asynchronous writes to the remote peer has completed.
+ // Make sure it succeeded and then delete the message.
+
+ virtual int handle_input_complete (ACE_Message_Block *msg,
+ long bytes_transfered);
+ // The remote peer has sent us something. If it succeeded, print
+ // out the message and reinitiate a read. Otherwise, fail. In both
+ // cases, delete the message sent.
+
+ virtual ACE_Message_Block *get_message (void);
+ // This is so the Proactor can get a message to read into.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // This is so the Proactor can get our handle.
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ // We've been removed from the ReactorEx.
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *);
+ // We've been signaled by the STDIN thread. Try to dequeue a
+ // message.
+
+ void try_send (void);
+ // Try to dequeue a message. If successful, send it proactively to
+ // the remote peer.
+
+ virtual int put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv = 0);
+ // Enqueue the new mb and signal the main thread.
+
+private:
+ ACE_SOCK_Stream stream_;
+ // Socket that we have connected to the server.
+
+ ACE_HANDLE new_msg_event_;
+ // Event that gets signaled when messages arrive.
+
+ // = Remote peer info.
+ char *host_;
+ // Name of remote host.
+
+ u_short port_;
+ // Port number for remote host.
+
+ // = Make Task happy.
+ int close (u_long) { return 0; }
+};
+
+class STDIN_Handler : public ACE_Task<ACE_NULL_SYNCH>
+ // = TITLE
+ // Active Object. Reads from STDIN and passes message blocks to
+ // the peer handler.
+{
+public:
+ STDIN_Handler (MT_TASK &ph);
+
+ virtual int open (void * = 0);
+ // Activate object.
+
+ virtual int close (u_long = 0);
+ // Shut down.
+
+ int svc (void);
+ // Thread runs here.
+
+private:
+ MT_TASK &ph_;
+ // Send all input to ph_.
+
+ static void handler (int signum);
+ // Handle a ^C. (Do nothing).
+
+ int put (ACE_Message_Block *, ACE_Time_Value *) { return 0; }
+ // Make Task happy.
+
+ void register_thread_exit_hook (void);
+ // Helper function to register with the ReactorEx for thread exit.
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *);
+ // The STDIN thread has exited. This means the user hit ^C. We can
+ // end the event loop.
+};
+
+Peer_Handler::Peer_Handler (int argc, char *argv[])
+ : host_ (0),
+ port_ (ACE_DEFAULT_SERVER_PORT)
+{
+ ACE_Get_Opt get_opt (argc, argv, "h:p:");
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ {
+ switch (c)
+ {
+ case 'h':
+ host_ = get_opt.optarg;
+ break;
+ case 'p':
+ port_ = ACE_OS::atoi (get_opt.optarg);
+ break;
+ }
+ }
+
+ // Auto reset event.
+ new_msg_event_ = ::CreateEvent (NULL, FALSE, FALSE, NULL);
+ ACE_Service_Config::reactorEx ()->
+ register_handler (this, new_msg_event_);
+}
+
+// This method creates the network connection to the remote peer. It
+// does blocking connects and accepts depending on whether a hostname
+// was specified from the command line.
+
+int
+Peer_Handler::open (void *)
+{
+ if (host_ != 0) // Connector
+ {
+ ACE_INET_Addr addr (port_, host_);
+ ACE_SOCK_Connector connector;
+
+ // Establish connection with server.
+ if (connector.connect (stream_, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "connect"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "connected.\n"));
+ }
+ else // Acceptor
+ {
+ ACE_SOCK_Acceptor acceptor;
+ ACE_INET_Addr local_addr (port_);
+
+ if ((acceptor.open (local_addr) == -1) ||
+ (acceptor.accept (this->stream_) == -1))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "accept failed"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "accepted.\n"));
+ }
+
+ return ACE_Service_Config::proactor ()->initiate
+ (this, ACE_Event_Handler::READ_MASK);
+}
+
+// One of our asynchronous writes to the remote peer has completed.
+// Make sure it succeeded and then delete the message.
+
+int
+Peer_Handler::handle_output_complete (ACE_Message_Block *msg,
+ long bytes_transfered)
+{
+ if (bytes_transfered <= 0)
+ ACE_DEBUG ((LM_DEBUG, "%p bytes = %d\n", "Message failed",
+ bytes_transfered));
+
+ // This was allocated by the STDIN_Handler, queued, dequeued,
+ // passed to the proactor, and now passed back to us.
+ delete msg;
+ return 0; // Do not reinvoke a send.
+}
+
+// The remote peer has sent us something. If it succeeded, print
+// out the message and reinitiate a read. Otherwise, fail. In both
+// cases, delete the message sent.
+
+int
+Peer_Handler::handle_input_complete (ACE_Message_Block *msg,
+ long bytes_transfered)
+{
+ if ((bytes_transfered > 0) && (msg->length () > 0))
+ {
+ msg->rd_ptr ()[bytes_transfered] = '\0';
+ // Print out the message received from the server.
+ ACE_DEBUG ((LM_DEBUG, "%s", msg->rd_ptr ()));
+ delete msg;
+ return 1; // Reinvokes the recv() operation!
+ }
+
+ delete msg;
+ // If a read failed, we will assume it's because the remote peer
+ // went away. We will end the event loop. Since we're in the main
+ // thread, we don't need to do a notify.
+ ACE_Service_Config::end_reactorEx_event_loop ();
+ return -1; // Close down.
+}
+
+// This is so the Proactor can get a message to read into.
+
+ACE_Message_Block *
+Peer_Handler::get_message (void)
+{
+ // An extra byte for NUL termination.
+ ACE_Message_Block *message =
+ new ACE_Message_Block (BUFSIZ + 1);
+
+ message->size (BUFSIZ);
+ return message;
+}
+
+// This is so the Proactor can get our handle.
+ACE_HANDLE
+Peer_Handler::get_handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+// We've been removed from the ReactorEx.
+int
+Peer_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Peer_Handler closing down\n"));
+ return 0;
+}
+
+// We've been signaled by the STDIN thread. Try to dequeue a
+// message.
+
+int
+Peer_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ this->try_send ();
+ return 0;
+}
+
+// Try to dequeue a message. If successful, send it proactively to
+// the remote peer.
+
+void
+Peer_Handler::try_send (void)
+{
+ ACE_Message_Block *mb;
+
+ ACE_Time_Value tv (ACE_Time_Value::zero);
+
+ if (this->getq (mb, &tv) != -1)
+ {
+ if (ACE_Service_Config::proactor ()->
+ initiate (this, ACE_Event_Handler::WRITE_MASK, mb) == -1)
+ ACE_ERROR ((LM_ERROR, "%p Write initiate.\n", "Peer_Handler"));
+ }
+}
+
+// Enqueue the new mb and signal the main thread.
+
+int
+Peer_Handler::put (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ // Enqueue the mb.
+ int result = this->putq (mb, tv);
+
+ // Signal the main thread. This will remain signaled until the main
+ // thread wakes up.
+
+ if (::SetEvent (new_msg_event_) == 0)
+ ACE_ERROR ((LM_ERROR, "Pulse Failed!\n"));
+
+ return result;
+}
+
+void
+STDIN_Handler::handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG, "signal = %S\n", signum));
+}
+
+STDIN_Handler::STDIN_Handler (MT_TASK &ph)
+ : ph_ (ph)
+{
+ // Register for ^C from the console. We just need to catch the
+ // exception so that the kernel doesn't kill our process.
+ // Registering this signal handler just tells the kernel that we
+ // know what we're doing; to leave us alone.
+ ACE_OS::signal (SIGINT, ACE_SignalHandler (STDIN_Handler::handler));
+};
+
+// Activate object.
+
+int
+STDIN_Handler::open (void *)
+{
+ if (this->activate (THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ return 0;
+}
+
+// Shut down.
+
+int
+STDIN_Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) thread is exiting.\n"));
+ return 0;
+}
+
+// Thread runs here.
+
+int
+STDIN_Handler::svc (void)
+{
+ this->register_thread_exit_hook ();
+
+ for (;;)
+ {
+ ACE_Message_Block *mb = new ACE_Message_Block (BUFSIZ);
+
+ // Read from stdin into mb.
+ int read_result = ACE_OS::read (ACE_STDIN,
+ mb->rd_ptr (),
+ mb->size ());
+
+ // If read succeeds, put mb to peer handler, else end the loop.
+ if (read_result > 0)
+ {
+ mb->wr_ptr (read_result);
+ this->ph_.put (mb);
+ }
+ else
+ break;
+ }
+
+ // handle_signal will get called.
+ return 42;
+}
+
+// Register an exit hook with the reactorEx. All this junk is testing
+// out how ACE_Thread::self (hthread_id&) doesn't work!!
+
+void
+STDIN_Handler::register_thread_exit_hook (void)
+{
+ ACE_hthread_t handle;
+
+ // Get a real handle to our thread.
+ ACE_Service_Config::thr_mgr ()->thr_self (handle);
+
+ // Register ourselves to get called back when our thread exits.
+
+ if (ACE_Service_Config::reactorEx ()->
+ register_handler (this, handle) == -1)
+ ACE_ERROR ((LM_ERROR, "Exit_Hook Register failed.\n"));
+
+ // We're in another thread, so we need to notify the ReactorEx so
+ // that it wakes up and waits on the new set of handles.
+ ACE_Service_Config::reactorEx ()->notify ();
+}
+
+// The STDIN thread has exited. This means the user hit ^C. We can
+// end the event loop and delete ourself.
+
+int
+STDIN_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ACE_DEBUG ((LM_DEBUG, "STDIN thread has exited.\n"));
+ ACE_Service_Config::end_reactorEx_event_loop ();
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ // Open handler for remote peer communications this will run from
+ // the main thread.
+ Peer_Handler peer_handler (argc, argv);
+
+ if (peer_handler.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p open failed, errno = %d.\n",
+ "peer_handler", errno), 0);
+
+ // Open active object for reading from stdin.
+ STDIN_Handler stdin_handler (peer_handler);
+
+ if (stdin_handler.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p open failed, errno = %d.\n",
+ "stdin_handler", errno), 0);
+
+ // Register proactor with ReactorEx so that we can demultiplex
+ // "waitable" events and I/O operations from a single thread.
+ if (ACE_Service_Config::reactorEx ()->register_handler
+ (ACE_Service_Config::proactor ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p failed to register Proactor.\n",
+ argv[0]), -1);
+
+ // Run main event demultiplexor.
+ ACE_Service_Config::run_reactorEx_event_loop ();
+
+ return 42;
+}
diff --git a/examples/Reactor/ReactorEx/test_remove_handler.cpp b/examples/Reactor/ReactorEx/test_remove_handler.cpp
new file mode 100644
index 00000000000..fb61519b1e9
--- /dev/null
+++ b/examples/Reactor/ReactorEx/test_remove_handler.cpp
@@ -0,0 +1,94 @@
+// ============================================================================
+// @(#)test_remove_handler.cpp 1.1 10/18/96
+
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_remove_handler.cpp
+//
+// = DESCRIPTION
+// Tests the ReactorEx's ability to handle simultaneous events. If
+// you pass anything on the command-line, then each handler
+// requests to be removed from the ReactorEx after each event.
+// This has a funky effect on the order in which handlers are
+// serviced. So, if no parameters are passed in, the handlers
+// should be serviced 1 through MAXIMUM_WAIT_OBJECTS. If handlers
+// to request to be removed as signals occur, they will be serviced
+// 1, MAX, MAX-1, ..., 2. This is because of a ReactorEx
+// bookkeeping optimization.
+//
+// = AUTHOR
+// Tim Harrison
+//
+// ============================================================================
+
+#include "ace/ReactorEx.h"
+#include "ace/Service_Config.h"
+#include "ace/Synch.h"
+
+class Event_Handler : public ACE_Event_Handler
+// = TITLE
+// Generic Event Handler.
+//
+// = DESCRIPTION
+//
+// Creates event. Registers with ReactorEx. Signals event. If
+// created with -close_down- it returns -1 from handle signal.
+{
+public:
+ Event_Handler (int event_number,
+ int close_down)
+ : event_number_ (event_number),
+ close_down_ (close_down)
+ {
+ ACE_Service_Config::reactorEx ()->register_handler (this,
+ this->event_.handle ());
+ this->event_.signal ();
+ }
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *)
+ {
+ ACE_DEBUG ((LM_DEBUG, "event %d occured.\n", event_number_));
+
+ if (this->close_down_)
+ return -1;
+ else
+ return 0;
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+ {
+ // ACE_DEBUG ((LM_DEBUG, "event handler %d closed.\n", event_number_));
+ delete this;
+ return 0;
+ }
+
+ virtual ACE_HANDLE get_handle (void) const
+ {
+ return event_.handle ();
+ }
+
+private:
+ int event_number_;
+ // Our event number.
+
+ int close_down_;
+ // Shall we close down or not.
+
+ ACE_Event event_;
+ // Signaled to shut down the handler.
+};
+
+int
+main (int argc, char *argv[])
+{
+ int close_down = arg > 1 ? 1 : 0;
+
+ for (int i = 0; i < ACE_ReactorEx::MAX_SIZE; i++)
+ new Event_Handler (i, close_down);
+
+ ACE_Service_Config::reactorEx ()->handle_events ();
+ return 42;
+}
diff --git a/examples/Reactor/WFMO_Reactor/README b/examples/Reactor/WFMO_Reactor/README
new file mode 100644
index 00000000000..1184d09dd68
--- /dev/null
+++ b/examples/Reactor/WFMO_Reactor/README
@@ -0,0 +1,204 @@
+The ACE_ReactorEx encapsulates the Win32 WaitForMultipleObjects() API
+within ACE. The ACE_ReactorEx is similar in spirit to the
+ACE_Reactor, except that (1) it is much simpler and (2) it works for
+the complete range of Win32 handles (whereas the ACE_Reactor just
+works for socket handles.
+
+Here's the API for the ACE_ReactorEx:
+
+class ACE_ReactorEx
+{
+public:
+ // = Event loop.
+ virtual int handle_events (ACE_Time_Value *);
+
+ // = Handler registration management.
+ virtual int register_handler (ACE_Event_Handler *);
+ virtual int remove_handler (ACE_Event_Handler *);
+
+ virtual int notify (void);
+
+ // = Timer management
+ virtual int schedule_timer (), etc.
+ // ...
+};
+
+----------------------------------------
+
+Here's how you might use it:
+
+----------------------------------------
+
+class My_Thread_Handler : public ACE_Event_Handler
+{
+public:
+ My_Thread_Handler (void) {
+ // Create a thread that will run
+ // for a time and then exit.
+ this->thread_handle_ =
+ ACE_OS::thr_create (run, ......);
+ }
+
+ // Called back by the ACE_ReactorEx when the
+ // event is signaled.
+ virtual int handle_signal (int)
+ {
+ cout << "thread is done" << endl;
+ }
+
+ virtual ACE_HANDLE get_handle (void) const
+ {
+ return this->thread_handle_;
+ }
+
+private:
+ ACE_HANDLE thread_handle_;
+
+ static void *run (void *) {
+ // Sleep for a while and then exit.
+ ACE_OS::sleep (100000);
+ return 0;
+ }
+};
+
+----------------------------------------
+
+The main program might look something like this:
+
+----------------------------------------
+
+int main (void)
+{
+ // ...
+ ACE_ReactorEx dispatcher;
+ My_Thread_Handler handler;
+
+ // Register the thread handler.
+ dispatcher.register_handler (&handler);
+
+ // Block until the thread exits and the
+ // handle_signal() method of the My_Thread_Handler
+ // is called!
+ dispatcher.handle_events ();
+
+ // ...
+}
+
+----------------------------------------
+
+. test_remove_handler --
+
+This application tests the ReactorEx's ability to handle simultaneous
+events. If you pass anything on the command-line, then each handler
+requests to be removed from the ReactorEx after each event. This has
+a funky effect on the order in which handlers are serviced. So, if no
+parameters are passed in, the handlers should be serviced 1 through
+MAXIMUM_WAIT_OBJECTS. If handlers to request to be removed as signals
+occur, they will be serviced 1, MAX, MAX-1, ..., 2. This is because
+of a ReactorEx bookkeeping optimization.
+
+. test_reactorEx.cpp --
+
+This test application tests a wide range of events that can be
+demultiplexed using various ACE utilities. Events used include ^C
+events, reading from STDIN, vanilla Win32 events, thread exits,
+ReactorEx notifications, proactive reads, and proactive writes.
+
+The proactive I/O events are demultiplexed by the ACE_Proactor. The
+thread exits, notications, and vanilla Win32 events are demultiplexed
+by the ACE_ReactorEx. To enable a single thread to run all these
+events, the Proactor is integrated with the ReactorEx.
+
+The test application prototypes a simple ntalk program. Two instances
+of the application connect. Input from either console is displayed on
+the others console also. Because of the evils of Win32 STDIN, a
+separate thread is used to read from STDIN. To test the Proactor and
+ReactorEx, I/O between the remote processes is performed proactively
+and interactions between the STDIN thread and the main thread are
+performed reactively.
+
+The following description of the test application is in two parts.
+The participants section explains the main components involved in the
+application. The collaboration section describes how the partipants
+interact in response to the multiple event types which occur.
+
+The ReactorEx test application has the following participants:
+
+. ReactorEx -- The ReactorEx demultiplexes Win32 "waitable" events
+ using WaitForMultipleObjects.
+
+. Proactor -- The proactor initiates and demultiplexes overlapped I/O
+ operations. The Proactor registers with the ReactorEx so that a
+ single-thread can demultiplex all application events.
+
+. STDIN_Handler -- STDIN_Handler is an Active Object which reads from
+ STDIN and forwards the input to the Peer_Handler. This runs
+ in a separate thread to make the test more interesting. However,
+ STDIN is "waitable", so in general it can be waited on by the ACE
+ ReactorEx, thanks MicroSlush!
+
+. Peer_Handler -- The Peer_Handler connects to another instance of
+ test_reactorEx. It Proactively reads and writes data to the peer.
+ When the STDIN_Handler gives it messages, it fowards them to the
+ remote peer. When it receives messages from the remote peer, it
+ prints the output to the console.
+
+The collaborations of the participants are as follows:
+
+. Initialization
+
+ Peer_Handler -- connects to the remote peer. It then begins
+ proactively reading from the remote connection. Note that it will
+ be notified by the Proactor when a read completes. It also
+ registers a new_msg_event with the ReactorEx. Note that when the
+ new_msg_event is signaled (by the STDIN_Handler),
+ Peer_Handler::handle_signal will get called.
+
+ STDIN_Handler -- STDIN_Handler registers a signal handler for
+ SIGINT. This just captures the exception so that the kernel doesn't
+ kill our process; We want to exit gracefully. It also creates an
+ Exit_Hook object which registers the STDIN_Handler's thread handle
+ with the ReactorEx. The Exit_Hook will get called back when the
+ STDIN_Handler thread exits. After registering these, it blocks
+ reading from STDIN.
+
+ Proactor -- is registered with the ReactorEx.
+
+ The main thread of control waits in the ReactorEx.
+
+. STDIN events -- When the STDIN_Handler thread reads from STDIN, it
+ puts the message on Peer_Handler's message queue and signals the
+ new_msg_event. It then returns to reading from STDIN.
+
+. new_msg_events -- The ReactorEx thread wakes up and calls
+ Peer_Handler::handle_signal. The Peer_Handler then tries to dequeue
+ a message from its message queue. If it can, the message is
+ Proactively sent to the remote peer. Note that the Peer_Handler
+ will be notified with this operation is complete. The Peer_Handler
+ then falls back into the ReactorEx event loop.
+
+. Send complete event -- When a proactive send is complete, the
+ Proactor is notified by the ReactorEx. The Proactor, in turn,
+ notifies the Peer_Handler. The Peer_Handler then checks for more
+ messages from the message queue. If there are any, it tries to send
+ them. If there are not, it returns to the ReactorEx event loop.
+ This is ok since it is notified via new_msg_event when new message
+ arrive.
+
+. Read complete event -- When a proactive read is complete (the
+ Peer_Handler initiated a proactive read when it connected to the
+ remote peer), the Proactor is notified by the ReactorEx. The
+ Proactor, in turn notifies the Peer_Handler. If the read was
+ successful the Peer_Handler just displays the received msg to the
+ console and reinvokes a proactive read from the network connection.
+ If the read failed (i.e. the remote peer exited), the Peer_Handler
+ sets a flag to end the event loop and returns. This will cause the
+ application to exit.
+
+. ^C events -- When the user types ^C at the console, the
+ STDIN_Handler's signal handler will be called. It does nothing, but
+ as a result of the signal, the STDIN_Handler thread will exit.
+
+. STDIN_Handler thread exits -- The Exit_Hook will get called back
+ from the ReactorEx. Exit_Hook::handle_signal sets a flag to end the
+ event loop and returns. This will cause the application to exit.
diff --git a/examples/Reactor/WFMO_Reactor/reactorex.mak b/examples/Reactor/WFMO_Reactor/reactorex.mak
new file mode 100644
index 00000000000..150d04508d7
--- /dev/null
+++ b/examples/Reactor/WFMO_Reactor/reactorex.mak
@@ -0,0 +1,535 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+!IF "$(CFG)" == ""
+CFG=test_remove_handler - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to test_remove_handler - Win32\
+ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ntalk - Win32 Release" && "$(CFG)" != "ntalk - Win32 Debug" &&\
+ "$(CFG)" != "test_remove_handler - Win32 Release" && "$(CFG)" !=\
+ "test_remove_handler - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "reactorEx.mak" CFG="test_remove_handler - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ntalk - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "ntalk - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "test_remove_handler - Win32 Release" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE "test_remove_handler - Win32 Debug" (based on\
+ "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "ntalk - Win32 Debug"
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ntalk - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ntalk\Release"
+# PROP BASE Intermediate_Dir "ntalk\Release"
+# PROP BASE Target_Dir "ntalk"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ntalk\Release"
+# PROP Intermediate_Dir "ntalk\Release"
+# PROP Target_Dir "ntalk"
+OUTDIR=.\ntalk\Release
+INTDIR=.\ntalk\Release
+
+ALL : "$(OUTDIR)\ntalk.exe"
+
+CLEAN :
+ -@erase ".\ntalk\Release\ntalk.exe"
+ -@erase ".\ntalk\Release\test_reactorEx.obj"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/ntalk.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\ntalk\Release/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntalk.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ace.lib /nologo /subsystem:console /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib ace.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)/ntalk.pdb" /machine:I386 /out:"$(OUTDIR)/ntalk.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_reactorEx.obj"
+
+"$(OUTDIR)\ntalk.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "ntalk - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ntalk\Debug"
+# PROP BASE Intermediate_Dir "ntalk\Debug"
+# PROP BASE Target_Dir "ntalk"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir "ntalk"
+OUTDIR=.
+INTDIR=.\debug
+
+ALL : "$(OUTDIR)\test_reactorEx.exe"
+
+CLEAN :
+ -@erase ".\debug\vc40.pdb"
+ -@erase ".\debug\vc40.idb"
+ -@erase ".\test_reactorEx.exe"
+ -@erase ".\debug\test_reactorEx.obj"
+ -@erase ".\test_reactorEx.ilk"
+ -@erase ".\test_reactorEx.pdb"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/ntalk.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\debug/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/ntalk.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ace.lib /nologo /subsystem:console /debug /machine:I386 /out:"test_reactorEx.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib ace.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)/test_reactorEx.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/test_reactorEx.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_reactorEx.obj"
+
+"$(OUTDIR)\test_reactorEx.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "test_remove_handler - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "test_remove_handler\Release"
+# PROP BASE Intermediate_Dir "test_remove_handler\Release"
+# PROP BASE Target_Dir "test_remove_handler"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "test_remove_handler\Release"
+# PROP Intermediate_Dir "test_remove_handler\Release"
+# PROP Target_Dir "test_remove_handler"
+OUTDIR=.\test_remove_handler\Release
+INTDIR=.\test_remove_handler\Release
+
+ALL : "$(OUTDIR)\test_remove_handler.exe"
+
+CLEAN :
+ -@erase ".\test_remove_handler\Release\test_remove_handler.exe"
+ -@erase ".\test_remove_handler\Release\test_remove_handler.obj"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/test_remove_handler.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\test_remove_handler\Release/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_remove_handler.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:console /incremental:no\
+ /pdb:"$(OUTDIR)/test_remove_handler.pdb" /machine:I386\
+ /out:"$(OUTDIR)/test_remove_handler.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_remove_handler.obj"
+
+"$(OUTDIR)\test_remove_handler.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "test_remove_handler - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "test_remove_handler\Debug"
+# PROP BASE Intermediate_Dir "test_remove_handler\Debug"
+# PROP BASE Target_Dir "test_remove_handler"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir "test_remove_handler"
+OUTDIR=.
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\test_remove_handler.exe"
+
+CLEAN :
+ -@erase ".\debug\vc40.pdb"
+ -@erase ".\debug\vc40.idb"
+ -@erase ".\test_remove_handler.exe"
+ -@erase ".\Debug\test_remove_handler.obj"
+ -@erase ".\test_remove_handler.ilk"
+ -@erase ".\test_remove_handler.pdb"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/test_remove_handler.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_remove_handler.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ace.lib /nologo /subsystem:console /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib ace.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)/test_remove_handler.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/test_remove_handler.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/test_remove_handler.obj"
+
+"$(OUTDIR)\test_remove_handler.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "ntalk - Win32 Release"
+# Name "ntalk - Win32 Debug"
+
+!IF "$(CFG)" == "ntalk - Win32 Release"
+
+!ELSEIF "$(CFG)" == "ntalk - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\test_reactorEx.cpp
+DEP_CPP_TEST_=\
+ {$(INCLUDE)}"\ace\ReactorEx.h"\
+ {$(INCLUDE)}"\ace\Proactor.h"\
+ {$(INCLUDE)}"\ace\SOCK_Connector.h"\
+ {$(INCLUDE)}"\ace\SOCK_Acceptor.h"\
+ {$(INCLUDE)}"\ace\Get_Opt.h"\
+ {$(INCLUDE)}"\ace\Time_Value.h"\
+ {$(INCLUDE)}"\ace\Service_Config.h"\
+ {$(INCLUDE)}"\ace\Synch.h"\
+ {$(INCLUDE)}"\ace\Task.h"\
+ {$(INCLUDE)}"\ace\OS.h"\
+ {$(INCLUDE)}"\ace\Timer_Queue.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.h"\
+ {$(INCLUDE)}"\ace\Token.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.h"\
+ {$(INCLUDE)}"\ace\ReactorEx.i"\
+ {$(INCLUDE)}"\ace\Timer_Queue.i"\
+ {$(INCLUDE)}"\ace\ACE.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.i"\
+ {$(INCLUDE)}"\ace\ACE.i"\
+ {$(INCLUDE)}"\ace\Log_Msg.h"\
+ {$(INCLUDE)}"\ace\Log_Record.h"\
+ {$(INCLUDE)}"\ace\Log_Priority.h"\
+ {$(INCLUDE)}"\ace\Log_Record.i"\
+ {$(INCLUDE)}"\ace\Token.i"\
+ {$(INCLUDE)}"\ace\Stack.h"\
+ {$(INCLUDE)}"\ace\Synch_Options.h"\
+ {$(INCLUDE)}"\ace\Map_Manager.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.i"\
+ {$(INCLUDE)}"\ace\Stack.i"\
+ {$(INCLUDE)}"\ace\Stack.cpp"\
+ {$(INCLUDE)}"\ace\Map_Manager.i"\
+ {$(INCLUDE)}"\ace\Map_Manager.cpp"\
+ {$(INCLUDE)}"\ace\Malloc.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.h"\
+ {$(INCLUDE)}"\ace\Malloc.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.i"\
+ {$(INCLUDE)}"\ace\Trace.h"\
+ {$(INCLUDE)}"\ace\Malloc_T.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.cpp"\
+ {$(INCLUDE)}"\ace\Signal.h"\
+ {$(INCLUDE)}"\ace\Mem_Map.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.i"\
+ {$(INCLUDE)}"\ace\Set.h"\
+ {$(INCLUDE)}"\ace\Signal.i"\
+ {$(INCLUDE)}"\ace\Set.i"\
+ {$(INCLUDE)}"\ace\Set.cpp"\
+ {$(INCLUDE)}"\ace\Mem_Map.i"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.i"\
+ {$(INCLUDE)}"\ace\Message_Block.h"\
+ {$(INCLUDE)}"\ace\Proactor.i"\
+ {$(INCLUDE)}"\ace\Message_Block.i"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.h"\
+ {$(INCLUDE)}"\ace\SOCK_Connector.i"\
+ {$(INCLUDE)}"\ace\SOCK_IO.h"\
+ {$(INCLUDE)}"\ace\INET_Addr.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.i"\
+ {$(INCLUDE)}"\ace\SOCK.h"\
+ {$(INCLUDE)}"\ace\SOCK_IO.i"\
+ {$(INCLUDE)}"\ace\Addr.h"\
+ {$(INCLUDE)}"\ace\IPC_SAP.h"\
+ {$(INCLUDE)}"\ace\SOCK.i"\
+ {$(INCLUDE)}"\ace\Addr.i"\
+ {$(INCLUDE)}"\ace\IPC_SAP.i"\
+ {$(INCLUDE)}"\ace\INET_Addr.i"\
+ {$(INCLUDE)}"\ace\SOCK_Acceptor.i"\
+ {$(INCLUDE)}"\ace\Get_Opt.i"\
+ {$(INCLUDE)}"\ace\config.h"\
+ {$(INCLUDE)}"\ace\Time_Value.i"\
+ {$(INCLUDE)}"\ace\Service_Object.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.h"\
+ {$(INCLUDE)}"\ace\Service_Config.i"\
+ {$(INCLUDE)}"\ace\Reactor.h"\
+ {$(INCLUDE)}"\ace\Svc_Conf_Tokens.h"\
+ {$(INCLUDE)}"\ace\Shared_Object.h"\
+ {$(INCLUDE)}"\ace\Service_Object.i"\
+ {$(INCLUDE)}"\ace\Shared_Object.i"\
+ {$(INCLUDE)}"\ace\Thread.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.i"\
+ {$(INCLUDE)}"\ace\Thread.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.h"\
+ {$(INCLUDE)}"\ace\Pipe.h"\
+ {$(INCLUDE)}"\ace\Reactor.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.i"\
+ {$(INCLUDE)}"\ace\Pipe.i"\
+ {$(INCLUDE)}"\ace\Synch.i"\
+ {$(INCLUDE)}"\ace\Synch_T.h"\
+ {$(INCLUDE)}"\ace\Synch_T.i"\
+ {$(INCLUDE)}"\ace\Synch_T.cpp"\
+ {$(INCLUDE)}"\ace\Message_Queue.h"\
+ {$(INCLUDE)}"\ace\Task.i"\
+ {$(INCLUDE)}"\ace\Task.cpp"\
+ {$(INCLUDE)}"\ace\IO_Cntl_Msg.h"\
+ {$(INCLUDE)}"\ace\Message_Queue.i"\
+ {$(INCLUDE)}"\ace\Message_Queue.cpp"\
+ {$(INCLUDE)}"\ace\Module.h"\
+ {$(INCLUDE)}"\ace\Module.i"\
+ {$(INCLUDE)}"\ace\Module.cpp"\
+ {$(INCLUDE)}"\ace\Stream_Modules.h"\
+ {$(INCLUDE)}"\ace\Stream_Modules.i"\
+ {$(INCLUDE)}"\ace\Stream_Modules.cpp"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TIMEB.H"\
+ {$(INCLUDE)}"\ace\OS.i"\
+
+NODEP_CPP_TEST_=\
+ ".\..\..\ace\ace\Sync_T.h"\
+ ".\..\..\ace\semLib.h"\
+
+
+"$(INTDIR)\test_reactorEx.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "test_remove_handler - Win32 Release"
+# Name "test_remove_handler - Win32 Debug"
+
+!IF "$(CFG)" == "test_remove_handler - Win32 Release"
+
+!ELSEIF "$(CFG)" == "test_remove_handler - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\test_remove_handler.cpp
+DEP_CPP_TEST_R=\
+ {$(INCLUDE)}"\ace\ReactorEx.h"\
+ {$(INCLUDE)}"\ace\Service_Config.h"\
+ {$(INCLUDE)}"\ace\Synch.h"\
+ {$(INCLUDE)}"\ace\Timer_Queue.h"\
+ {$(INCLUDE)}"\ace\Time_Value.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.h"\
+ {$(INCLUDE)}"\ace\Token.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.h"\
+ {$(INCLUDE)}"\ace\ReactorEx.i"\
+ {$(INCLUDE)}"\ace\Timer_Queue.i"\
+ {$(INCLUDE)}"\ace\config.h"\
+ {$(INCLUDE)}"\ace\Time_Value.i"\
+ {$(INCLUDE)}"\ace\Trace.h"\
+ {$(INCLUDE)}"\ace\ACE.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.i"\
+ {$(INCLUDE)}"\ace\OS.h"\
+ {$(INCLUDE)}"\ace\ACE.i"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TIMEB.H"\
+ {$(INCLUDE)}"\ace\OS.i"\
+ {$(INCLUDE)}"\ace\Log_Msg.h"\
+ {$(INCLUDE)}"\ace\Log_Record.h"\
+ {$(INCLUDE)}"\ace\Log_Priority.h"\
+ {$(INCLUDE)}"\ace\Log_Record.i"\
+ {$(INCLUDE)}"\ace\Token.i"\
+ {$(INCLUDE)}"\ace\Stack.h"\
+ {$(INCLUDE)}"\ace\Synch_Options.h"\
+ {$(INCLUDE)}"\ace\Map_Manager.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.i"\
+ {$(INCLUDE)}"\ace\Stack.i"\
+ {$(INCLUDE)}"\ace\Stack.cpp"\
+ {$(INCLUDE)}"\ace\Map_Manager.i"\
+ {$(INCLUDE)}"\ace\Map_Manager.cpp"\
+ {$(INCLUDE)}"\ace\Malloc.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.h"\
+ {$(INCLUDE)}"\ace\Malloc.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.cpp"\
+ {$(INCLUDE)}"\ace\Signal.h"\
+ {$(INCLUDE)}"\ace\Mem_Map.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.i"\
+ {$(INCLUDE)}"\ace\Set.h"\
+ {$(INCLUDE)}"\ace\Signal.i"\
+ {$(INCLUDE)}"\ace\Set.i"\
+ {$(INCLUDE)}"\ace\Set.cpp"\
+ {$(INCLUDE)}"\ace\Mem_Map.i"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.i"\
+ {$(INCLUDE)}"\ace\Service_Object.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.h"\
+ {$(INCLUDE)}"\ace\Proactor.h"\
+ {$(INCLUDE)}"\ace\Service_Config.i"\
+ {$(INCLUDE)}"\ace\Reactor.h"\
+ {$(INCLUDE)}"\ace\Svc_Conf_Tokens.h"\
+ {$(INCLUDE)}"\ace\Shared_Object.h"\
+ {$(INCLUDE)}"\ace\Service_Object.i"\
+ {$(INCLUDE)}"\ace\Shared_Object.i"\
+ {$(INCLUDE)}"\ace\Thread.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.i"\
+ {$(INCLUDE)}"\ace\Thread.i"\
+ {$(INCLUDE)}"\ace\Message_Block.h"\
+ {$(INCLUDE)}"\ace\Proactor.i"\
+ {$(INCLUDE)}"\ace\Message_Block.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.h"\
+ {$(INCLUDE)}"\ace\Pipe.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.h"\
+ {$(INCLUDE)}"\ace\Reactor.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.i"\
+ {$(INCLUDE)}"\ace\Pipe.i"\
+ {$(INCLUDE)}"\ace\SOCK_IO.h"\
+ {$(INCLUDE)}"\ace\INET_Addr.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.i"\
+ {$(INCLUDE)}"\ace\SOCK.h"\
+ {$(INCLUDE)}"\ace\SOCK_IO.i"\
+ {$(INCLUDE)}"\ace\Addr.h"\
+ {$(INCLUDE)}"\ace\IPC_SAP.h"\
+ {$(INCLUDE)}"\ace\SOCK.i"\
+ {$(INCLUDE)}"\ace\Addr.i"\
+ {$(INCLUDE)}"\ace\IPC_SAP.i"\
+ {$(INCLUDE)}"\ace\INET_Addr.i"\
+ {$(INCLUDE)}"\ace\Synch.i"\
+ {$(INCLUDE)}"\ace\Synch_T.h"\
+ {$(INCLUDE)}"\ace\Synch_T.i"\
+ {$(INCLUDE)}"\ace\Synch_T.cpp"\
+
+NODEP_CPP_TEST_R=\
+ ".\..\..\ace\semLib.h"\
+ ".\..\..\ace\ace\Sync_T.h"\
+
+
+"$(INTDIR)\test_remove_handler.obj" : $(SOURCE) $(DEP_CPP_TEST_R) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/examples/Reactor/WFMO_Reactor/reactorex.mdp b/examples/Reactor/WFMO_Reactor/reactorex.mdp
new file mode 100644
index 00000000000..0135cc67b75
--- /dev/null
+++ b/examples/Reactor/WFMO_Reactor/reactorex.mdp
Binary files differ
diff --git a/examples/Reactor/WFMO_Reactor/test_reactorEx.cpp b/examples/Reactor/WFMO_Reactor/test_reactorEx.cpp
new file mode 100644
index 00000000000..757e78c1e9e
--- /dev/null
+++ b/examples/Reactor/WFMO_Reactor/test_reactorEx.cpp
@@ -0,0 +1,444 @@
+// ============================================================================
+// @(#)test_reactorEx.cpp 1.1 10/18/96
+
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_reactorEx.cpp
+//
+// = DESCRIPTION
+// This test application tests a wide range of events that can be
+// demultiplexed using various ACE utilities. Events used include ^C
+// events, reading from STDIN, vanilla Win32 events, thread exits,
+// ReactorEx notifications, proactive reads, and proactive writes.
+//
+// The proactive I/O events are demultiplexed by the ACE_Proactor.
+// The thread exits, notications, and vanilla Win32 events are
+// demultiplexed by the ACE_ReactorEx. To enable a single thread
+// to run all these events, the Proactor is integrated with the
+// ReactorEx.
+//
+// = AUTHOR
+// Tim Harrison
+//
+// ============================================================================
+
+#include "ace/ReactorEx.h"
+#include "ace/Proactor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Get_Opt.h"
+#include "ace/Time_Value.h"
+#include "ace/Service_Config.h"
+#include "ace/Synch.h"
+#include "ace/Task.h"
+#include "ace/OS.h"
+
+typedef ACE_Task<ACE_MT_SYNCH> MT_TASK;
+
+class Peer_Handler : public MT_TASK
+ // = TITLE
+ // Connect to a server. Receive messages from STDIN_Handler
+ // and forward them to the server using proactive I/O.
+{
+public:
+ Peer_Handler (int argc, char *argv[]);
+
+ int open (void * =0);
+ // This method creates the network connection to the remote peer.
+ // It does blocking connects and accepts depending on whether a
+ // hostname was specified from the command line.
+
+ virtual int handle_output_complete (ACE_Message_Block *msg,
+ long bytes_transfered);
+ // One of our asynchronous writes to the remote peer has completed.
+ // Make sure it succeeded and then delete the message.
+
+ virtual int handle_input_complete (ACE_Message_Block *msg,
+ long bytes_transfered);
+ // The remote peer has sent us something. If it succeeded, print
+ // out the message and reinitiate a read. Otherwise, fail. In both
+ // cases, delete the message sent.
+
+ virtual ACE_Message_Block *get_message (void);
+ // This is so the Proactor can get a message to read into.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // This is so the Proactor can get our handle.
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ // We've been removed from the ReactorEx.
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *);
+ // We've been signaled by the STDIN thread. Try to dequeue a
+ // message.
+
+ void try_send (void);
+ // Try to dequeue a message. If successful, send it proactively to
+ // the remote peer.
+
+ virtual int put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv = 0);
+ // Enqueue the new mb and signal the main thread.
+
+private:
+ ACE_SOCK_Stream stream_;
+ // Socket that we have connected to the server.
+
+ ACE_HANDLE new_msg_event_;
+ // Event that gets signaled when messages arrive.
+
+ // = Remote peer info.
+ char *host_;
+ // Name of remote host.
+
+ u_short port_;
+ // Port number for remote host.
+
+ // = Make Task happy.
+ int close (u_long) { return 0; }
+};
+
+class STDIN_Handler : public ACE_Task<ACE_NULL_SYNCH>
+ // = TITLE
+ // Active Object. Reads from STDIN and passes message blocks to
+ // the peer handler.
+{
+public:
+ STDIN_Handler (MT_TASK &ph);
+
+ virtual int open (void * = 0);
+ // Activate object.
+
+ virtual int close (u_long = 0);
+ // Shut down.
+
+ int svc (void);
+ // Thread runs here.
+
+private:
+ MT_TASK &ph_;
+ // Send all input to ph_.
+
+ static void handler (int signum);
+ // Handle a ^C. (Do nothing).
+
+ int put (ACE_Message_Block *, ACE_Time_Value *) { return 0; }
+ // Make Task happy.
+
+ void register_thread_exit_hook (void);
+ // Helper function to register with the ReactorEx for thread exit.
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *);
+ // The STDIN thread has exited. This means the user hit ^C. We can
+ // end the event loop.
+};
+
+Peer_Handler::Peer_Handler (int argc, char *argv[])
+ : host_ (0),
+ port_ (ACE_DEFAULT_SERVER_PORT)
+{
+ ACE_Get_Opt get_opt (argc, argv, "h:p:");
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ {
+ switch (c)
+ {
+ case 'h':
+ host_ = get_opt.optarg;
+ break;
+ case 'p':
+ port_ = ACE_OS::atoi (get_opt.optarg);
+ break;
+ }
+ }
+
+ // Auto reset event.
+ new_msg_event_ = ::CreateEvent (NULL, FALSE, FALSE, NULL);
+ ACE_Service_Config::reactorEx ()->
+ register_handler (this, new_msg_event_);
+}
+
+// This method creates the network connection to the remote peer. It
+// does blocking connects and accepts depending on whether a hostname
+// was specified from the command line.
+
+int
+Peer_Handler::open (void *)
+{
+ if (host_ != 0) // Connector
+ {
+ ACE_INET_Addr addr (port_, host_);
+ ACE_SOCK_Connector connector;
+
+ // Establish connection with server.
+ if (connector.connect (stream_, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "connect"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "connected.\n"));
+ }
+ else // Acceptor
+ {
+ ACE_SOCK_Acceptor acceptor;
+ ACE_INET_Addr local_addr (port_);
+
+ if ((acceptor.open (local_addr) == -1) ||
+ (acceptor.accept (this->stream_) == -1))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "accept failed"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "accepted.\n"));
+ }
+
+ return ACE_Service_Config::proactor ()->initiate
+ (this, ACE_Event_Handler::READ_MASK);
+}
+
+// One of our asynchronous writes to the remote peer has completed.
+// Make sure it succeeded and then delete the message.
+
+int
+Peer_Handler::handle_output_complete (ACE_Message_Block *msg,
+ long bytes_transfered)
+{
+ if (bytes_transfered <= 0)
+ ACE_DEBUG ((LM_DEBUG, "%p bytes = %d\n", "Message failed",
+ bytes_transfered));
+
+ // This was allocated by the STDIN_Handler, queued, dequeued,
+ // passed to the proactor, and now passed back to us.
+ delete msg;
+ return 0; // Do not reinvoke a send.
+}
+
+// The remote peer has sent us something. If it succeeded, print
+// out the message and reinitiate a read. Otherwise, fail. In both
+// cases, delete the message sent.
+
+int
+Peer_Handler::handle_input_complete (ACE_Message_Block *msg,
+ long bytes_transfered)
+{
+ if ((bytes_transfered > 0) && (msg->length () > 0))
+ {
+ msg->rd_ptr ()[bytes_transfered] = '\0';
+ // Print out the message received from the server.
+ ACE_DEBUG ((LM_DEBUG, "%s", msg->rd_ptr ()));
+ delete msg;
+ return 1; // Reinvokes the recv() operation!
+ }
+
+ delete msg;
+ // If a read failed, we will assume it's because the remote peer
+ // went away. We will end the event loop. Since we're in the main
+ // thread, we don't need to do a notify.
+ ACE_Service_Config::end_reactorEx_event_loop ();
+ return -1; // Close down.
+}
+
+// This is so the Proactor can get a message to read into.
+
+ACE_Message_Block *
+Peer_Handler::get_message (void)
+{
+ // An extra byte for NUL termination.
+ ACE_Message_Block *message =
+ new ACE_Message_Block (BUFSIZ + 1);
+
+ message->size (BUFSIZ);
+ return message;
+}
+
+// This is so the Proactor can get our handle.
+ACE_HANDLE
+Peer_Handler::get_handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+// We've been removed from the ReactorEx.
+int
+Peer_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Peer_Handler closing down\n"));
+ return 0;
+}
+
+// We've been signaled by the STDIN thread. Try to dequeue a
+// message.
+
+int
+Peer_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ this->try_send ();
+ return 0;
+}
+
+// Try to dequeue a message. If successful, send it proactively to
+// the remote peer.
+
+void
+Peer_Handler::try_send (void)
+{
+ ACE_Message_Block *mb;
+
+ ACE_Time_Value tv (ACE_Time_Value::zero);
+
+ if (this->getq (mb, &tv) != -1)
+ {
+ if (ACE_Service_Config::proactor ()->
+ initiate (this, ACE_Event_Handler::WRITE_MASK, mb) == -1)
+ ACE_ERROR ((LM_ERROR, "%p Write initiate.\n", "Peer_Handler"));
+ }
+}
+
+// Enqueue the new mb and signal the main thread.
+
+int
+Peer_Handler::put (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ // Enqueue the mb.
+ int result = this->putq (mb, tv);
+
+ // Signal the main thread. This will remain signaled until the main
+ // thread wakes up.
+
+ if (::SetEvent (new_msg_event_) == 0)
+ ACE_ERROR ((LM_ERROR, "Pulse Failed!\n"));
+
+ return result;
+}
+
+void
+STDIN_Handler::handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG, "signal = %S\n", signum));
+}
+
+STDIN_Handler::STDIN_Handler (MT_TASK &ph)
+ : ph_ (ph)
+{
+ // Register for ^C from the console. We just need to catch the
+ // exception so that the kernel doesn't kill our process.
+ // Registering this signal handler just tells the kernel that we
+ // know what we're doing; to leave us alone.
+ ACE_OS::signal (SIGINT, ACE_SignalHandler (STDIN_Handler::handler));
+};
+
+// Activate object.
+
+int
+STDIN_Handler::open (void *)
+{
+ if (this->activate (THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ return 0;
+}
+
+// Shut down.
+
+int
+STDIN_Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) thread is exiting.\n"));
+ return 0;
+}
+
+// Thread runs here.
+
+int
+STDIN_Handler::svc (void)
+{
+ this->register_thread_exit_hook ();
+
+ for (;;)
+ {
+ ACE_Message_Block *mb = new ACE_Message_Block (BUFSIZ);
+
+ // Read from stdin into mb.
+ int read_result = ACE_OS::read (ACE_STDIN,
+ mb->rd_ptr (),
+ mb->size ());
+
+ // If read succeeds, put mb to peer handler, else end the loop.
+ if (read_result > 0)
+ {
+ mb->wr_ptr (read_result);
+ this->ph_.put (mb);
+ }
+ else
+ break;
+ }
+
+ // handle_signal will get called.
+ return 42;
+}
+
+// Register an exit hook with the reactorEx. All this junk is testing
+// out how ACE_Thread::self (hthread_id&) doesn't work!!
+
+void
+STDIN_Handler::register_thread_exit_hook (void)
+{
+ ACE_hthread_t handle;
+
+ // Get a real handle to our thread.
+ ACE_Service_Config::thr_mgr ()->thr_self (handle);
+
+ // Register ourselves to get called back when our thread exits.
+
+ if (ACE_Service_Config::reactorEx ()->
+ register_handler (this, handle) == -1)
+ ACE_ERROR ((LM_ERROR, "Exit_Hook Register failed.\n"));
+
+ // We're in another thread, so we need to notify the ReactorEx so
+ // that it wakes up and waits on the new set of handles.
+ ACE_Service_Config::reactorEx ()->notify ();
+}
+
+// The STDIN thread has exited. This means the user hit ^C. We can
+// end the event loop and delete ourself.
+
+int
+STDIN_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ACE_DEBUG ((LM_DEBUG, "STDIN thread has exited.\n"));
+ ACE_Service_Config::end_reactorEx_event_loop ();
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ // Open handler for remote peer communications this will run from
+ // the main thread.
+ Peer_Handler peer_handler (argc, argv);
+
+ if (peer_handler.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p open failed, errno = %d.\n",
+ "peer_handler", errno), 0);
+
+ // Open active object for reading from stdin.
+ STDIN_Handler stdin_handler (peer_handler);
+
+ if (stdin_handler.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p open failed, errno = %d.\n",
+ "stdin_handler", errno), 0);
+
+ // Register proactor with ReactorEx so that we can demultiplex
+ // "waitable" events and I/O operations from a single thread.
+ if (ACE_Service_Config::reactorEx ()->register_handler
+ (ACE_Service_Config::proactor ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p failed to register Proactor.\n",
+ argv[0]), -1);
+
+ // Run main event demultiplexor.
+ ACE_Service_Config::run_reactorEx_event_loop ();
+
+ return 42;
+}
diff --git a/examples/Reactor/WFMO_Reactor/test_remove_handler.cpp b/examples/Reactor/WFMO_Reactor/test_remove_handler.cpp
new file mode 100644
index 00000000000..fb61519b1e9
--- /dev/null
+++ b/examples/Reactor/WFMO_Reactor/test_remove_handler.cpp
@@ -0,0 +1,94 @@
+// ============================================================================
+// @(#)test_remove_handler.cpp 1.1 10/18/96
+
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_remove_handler.cpp
+//
+// = DESCRIPTION
+// Tests the ReactorEx's ability to handle simultaneous events. If
+// you pass anything on the command-line, then each handler
+// requests to be removed from the ReactorEx after each event.
+// This has a funky effect on the order in which handlers are
+// serviced. So, if no parameters are passed in, the handlers
+// should be serviced 1 through MAXIMUM_WAIT_OBJECTS. If handlers
+// to request to be removed as signals occur, they will be serviced
+// 1, MAX, MAX-1, ..., 2. This is because of a ReactorEx
+// bookkeeping optimization.
+//
+// = AUTHOR
+// Tim Harrison
+//
+// ============================================================================
+
+#include "ace/ReactorEx.h"
+#include "ace/Service_Config.h"
+#include "ace/Synch.h"
+
+class Event_Handler : public ACE_Event_Handler
+// = TITLE
+// Generic Event Handler.
+//
+// = DESCRIPTION
+//
+// Creates event. Registers with ReactorEx. Signals event. If
+// created with -close_down- it returns -1 from handle signal.
+{
+public:
+ Event_Handler (int event_number,
+ int close_down)
+ : event_number_ (event_number),
+ close_down_ (close_down)
+ {
+ ACE_Service_Config::reactorEx ()->register_handler (this,
+ this->event_.handle ());
+ this->event_.signal ();
+ }
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *)
+ {
+ ACE_DEBUG ((LM_DEBUG, "event %d occured.\n", event_number_));
+
+ if (this->close_down_)
+ return -1;
+ else
+ return 0;
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+ {
+ // ACE_DEBUG ((LM_DEBUG, "event handler %d closed.\n", event_number_));
+ delete this;
+ return 0;
+ }
+
+ virtual ACE_HANDLE get_handle (void) const
+ {
+ return event_.handle ();
+ }
+
+private:
+ int event_number_;
+ // Our event number.
+
+ int close_down_;
+ // Shall we close down or not.
+
+ ACE_Event event_;
+ // Signaled to shut down the handler.
+};
+
+int
+main (int argc, char *argv[])
+{
+ int close_down = arg > 1 ? 1 : 0;
+
+ for (int i = 0; i < ACE_ReactorEx::MAX_SIZE; i++)
+ new Event_Handler (i, close_down);
+
+ ACE_Service_Config::reactorEx ()->handle_events ();
+ return 42;
+}