summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ACE/ChangeLog27
-rw-r--r--ACE/ace/Connector.cpp29
-rw-r--r--ACE/ace/Connector.h6
-rw-r--r--ACE/ace/Strategies_T.cpp4
-rw-r--r--ACE/tests/MT_NonBlocking_Connect_Test.cpp406
-rw-r--r--ACE/tests/NonBlocking_Conn_Test.cpp85
-rw-r--r--ACE/tests/NonBlocking_Conn_Test.h14
-rw-r--r--ACE/tests/Process_Strategy_Test.cpp14
-rw-r--r--ACE/tests/run_test.lst1
-rw-r--r--ACE/tests/tests.mpc9
10 files changed, 556 insertions, 39 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog
index 1887c1a3a1f..96b4d79fde9 100644
--- a/ACE/ChangeLog
+++ b/ACE/ChangeLog
@@ -1,3 +1,30 @@
+Wed Mar 17 11:58:10 UTC 2010 Vladimir Zykov <vladimir.zykov@prismtech.com>
+
+ Committed the changes that I had to revert before x.7.7.
+
+ * ace/Strategies_T.cpp:
+ Changed the code so that close() is called in case of failure
+ instead of destroy().
+
+ * ace/Connector.cpp:
+ * ace/Connector.h:
+ Changed the fix for bug#3731. Now NBCH adds a reference in
+ constructor and removes it in destructor if the SVC_HANDLER that
+ it owns is reference counted. This is a cleaner solution than the
+ one used before.
+
+ * tests/NonBlocking_Conn_Test.h:
+ * tests/Process_Strategy_Test.cpp:
+ * tests/NonBlocking_Conn_Test.cpp:
+ Extended NonBlocking_Conn_Test and changed Process_Strategy_Test
+ because of the change in Strategies_T.cpp.
+
+ * tests/MT_NonBlocking_Connect_Test.cpp:
+ * tests/tests.mpc:
+ * tests/run_test.lst:
+ Added a new test. This can be a reproducer for the bug#3731 which
+ currently doesn't have its own test.
+
Wed Mar 17 08:57:30 UTC 2010 Vladimir Zykov <vladimir.zykov@prismtech.com>
* ace/Service_Gestalt.h:
diff --git a/ACE/ace/Connector.cpp b/ACE/ace/Connector.cpp
index db184ac1253..867fc572384 100644
--- a/ACE/ace/Connector.cpp
+++ b/ACE/ace/Connector.cpp
@@ -24,6 +24,7 @@ ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler
long id)
: connector_ (connector)
, svc_handler_ (sh)
+ , cleanup_svc_handler_ (0)
, timer_id_ (id)
{
ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler");
@@ -31,8 +32,25 @@ ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler
this->reference_counting_policy ().value
(ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
- if (this->svc_handler_ != 0)
- this->svc_handler_->add_reference ();
+ if (this->svc_handler_ != 0 &&
+ this->svc_handler_->reference_counting_policy ().value () ==
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED)
+ {
+ // If SVC_HANDLER is reference counted then NBCH holds a reference
+ // in cleanup_svc_handle_ which is both a pointer to SVC_HANDLER
+ // and a flag that triggers remove_reference in NBCH destructor.
+ this->cleanup_svc_handler_ = sh;
+ this->cleanup_svc_handler_->add_reference ();
+ }
+}
+
+template <class SVC_HANDLER>
+ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::~ACE_NonBlocking_Connect_Handler (void)
+{
+ if (this->cleanup_svc_handler_)
+ {
+ this->cleanup_svc_handler_->remove_reference ();
+ }
}
template <class SVC_HANDLER> SVC_HANDLER *
@@ -132,9 +150,6 @@ ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout
svc_handler->handle_close (svc_handler->get_handle (),
ACE_Event_Handler::TIMER_MASK);
- if (svc_handler != 0)
- svc_handler->remove_reference ();
-
return retval;
}
@@ -153,8 +168,6 @@ ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input (ACE_HANDLE)
if (svc_handler != 0)
{
svc_handler->close (NORMAL_CLOSE_OPERATION);
-
- svc_handler->remove_reference ();
}
return retval;
@@ -174,8 +187,6 @@ ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output (ACE_HANDLE handle)
if (svc_handler != 0)
{
connector.initialize_svc_handler (handle, svc_handler);
-
- svc_handler->remove_reference ();
}
return retval;
diff --git a/ACE/ace/Connector.h b/ACE/ace/Connector.h
index 4ba8c7ce3dd..5d77ae430e4 100644
--- a/ACE/ace/Connector.h
+++ b/ACE/ace/Connector.h
@@ -67,6 +67,9 @@ public:
SVC_HANDLER *,
long timer_id);
+ /// Destructor.
+ ~ACE_NonBlocking_Connect_Handler (void);
+
/// Close up and return underlying SVC_HANDLER through @c sh.
/**
* If the return value is true the close was performed succesfully,
@@ -127,6 +130,9 @@ private:
/// Associated SVC_HANDLER.
SVC_HANDLER *svc_handler_;
+ /// Same as svc_handler_ if svc_handler_ is reference counted.
+ SVC_HANDLER *cleanup_svc_handler_;
+
/// Associated timer id.
long timer_id_;
};
diff --git a/ACE/ace/Strategies_T.cpp b/ACE/ace/Strategies_T.cpp
index 6aaef5eb2cc..4addb7d3774 100644
--- a/ACE/ace/Strategies_T.cpp
+++ b/ACE/ace/Strategies_T.cpp
@@ -439,7 +439,7 @@ ACE_Process_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *svc_handle
case -1:
{
ACE_Errno_Guard error (errno);
- svc_handler->destroy ();
+ svc_handler->close ();
}
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%p\n"),
@@ -462,7 +462,7 @@ ACE_Process_Strategy<SVC_HANDLER>::activate_svc_handler (SVC_HANDLER *svc_handle
default: // In parent process.
// We need to close down the <SVC_HANDLER> here because it's
// running in the child.
- svc_handler->destroy ();
+ svc_handler->close ();
return 0;
}
}
diff --git a/ACE/tests/MT_NonBlocking_Connect_Test.cpp b/ACE/tests/MT_NonBlocking_Connect_Test.cpp
new file mode 100644
index 00000000000..7fcf1337277
--- /dev/null
+++ b/ACE/tests/MT_NonBlocking_Connect_Test.cpp
@@ -0,0 +1,406 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// MT_NonBlocking_Connect_Test.cpp
+//
+// = DESCRIPTION
+//
+// This test makes non-blocking connects from multiple threads. Things are
+// complicated by the fact that after the connection is attempted reactor's
+// handle_events() is called and this leads to possible connection
+// completion in the other thread. This is similar to what TAO does for
+// oneway with SYNC_NONE sync scope policy.
+// The following reactors are tested: Select, TP, WFMO, and Dev Poll
+// (if enabled).
+//
+// = AUTHOR
+// Vladimir Zykov <vladimir.zykov@prismtech.com>
+//
+// ============================================================================
+
+#include "test_config.h"
+#include "ace/Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/TP_Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/Dev_Poll_Reactor.h"
+#include "ace/Svc_Handler.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Get_Opt.h"
+#include "ace/Task.h"
+#include "ace/Connector.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Thread_Mutex.h"
+
+ACE_RCSID(tests,
+ MT_NonBlocking_Connect_Test,
+ "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+static int test_select_reactor = 1;
+static int test_tp_reactor = 1;
+static int test_wfmo_reactor = 1;
+static int test_dev_poll_reactor = 1;
+static int number_of_threads = 10;
+static int debug = 0;
+static int result = 0;
+
+static const ACE_TCHAR* hosts[] = {
+ ACE_TEXT ("www.russiantvguide.com:80"),
+ ACE_TEXT ("news.bbc.co.uk:80"),
+ ACE_TEXT ("www.cnn.com:80"),
+ ACE_TEXT ("www.waca.com.au:80"),
+ ACE_TEXT ("www.uganda.co.ug:80"),
+ ACE_TEXT ("www.cs.wustl.edu:80"),
+ ACE_TEXT ("www.dre.vanderbilt.edu:80"),
+ ACE_TEXT ("www.dhm.gov.np:80"),
+ ACE_TEXT ("www.msn.com:80"),
+ ACE_TEXT ("www.presidencymaldives.gov.mv:80")
+};
+
+class Svc_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+public:
+ Svc_Handler (void)
+ {
+ ACE_TEST_ASSERT (0);
+ }
+
+ Svc_Handler (ACE_Thread_Manager *);
+
+ int open (void *);
+
+ int close (u_long flags);
+
+ bool connected_;
+};
+
+Svc_Handler::Svc_Handler (ACE_Thread_Manager *)
+ : connected_ (false)
+{
+ this->reference_counting_policy ().value (
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
+}
+
+int
+Svc_Handler::open (void *)
+{
+ this->connected_ = true;
+ return 0;
+}
+
+int
+Svc_Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "%t close connection on handle %d.\n",
+ this->get_handle ()));
+ return 0;
+}
+
+template<class SVC_HANDLER>
+class Concurrency_Strategy :
+ public ACE_Concurrency_Strategy<SVC_HANDLER>
+{
+public:
+ virtual int activate_svc_handler (SVC_HANDLER *svc_handler, void *arg);
+};
+
+template<class SVC_HANDLER> int
+Concurrency_Strategy<SVC_HANDLER>::
+ activate_svc_handler (SVC_HANDLER *svc_handler, void *arg)
+{
+ // Every fourth connection fails.
+ static long count = 0;
+ if (++count % 4 == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%t connection on handle %d has artificially failed.\n",
+ svc_handler->get_handle ()));
+ return -1;
+ }
+ else
+ {
+ return ACE_Concurrency_Strategy<SVC_HANDLER>::activate_svc_handler (
+ svc_handler, arg);
+ }
+}
+
+typedef ACE_Creation_Strategy<Svc_Handler> CREATION_STRATEGY;
+typedef ACE_Connect_Strategy<Svc_Handler,
+ ACE_SOCK_CONNECTOR> CONNECT_STRATEGY;
+typedef Concurrency_Strategy<Svc_Handler> CONCURRENCY_STRATEGY;
+typedef ACE_Strategy_Connector<Svc_Handler,
+ ACE_SOCK_CONNECTOR> BASE_CONNECTOR;
+
+class Connect_Thread : public ACE_Task_Base
+{
+public:
+ Connect_Thread (ACE_Thread_Manager &thread_manager,
+ ACE_Reactor &reactor,
+ ACE_Thread_Mutex &reactor_lock)
+ : ACE_Task_Base (&thread_manager)
+ , reactor_ (reactor)
+ , reactor_lock_ (reactor_lock)
+ , threads_ (number_of_threads)
+ {
+ // Open the connector.
+ this->base_connector_.open (&this->reactor_,
+ &this->cns_, &this->cts_, &this->cys_);
+ }
+
+ int svc (void);
+
+private:
+ ACE_Reactor &reactor_;
+ ACE_Thread_Mutex &reactor_lock_;
+
+ CREATION_STRATEGY cns_;
+ CONNECT_STRATEGY cts_;
+ CONCURRENCY_STRATEGY cys_;
+ BASE_CONNECTOR base_connector_;
+
+ ACE_Atomic_Op<ACE_Thread_Mutex, long> threads_;
+};
+
+int
+Connect_Thread::svc (void)
+{
+ size_t const nr_names = sizeof hosts / sizeof (char *);
+ ACE_INET_Addr *addresses = new ACE_INET_Addr[nr_names];
+
+ for (size_t i = 0; i < nr_names; ++i)
+ {
+ if (addresses[i].set (hosts[i]) != 0)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("%p\n"),
+ hosts[i]));
+ }
+ }
+
+ ACE_INET_Addr local_addr;
+ ACE_Synch_Options synch_options (ACE_Synch_Options::USE_REACTOR);
+
+ for (size_t i = 0; i < nr_names; ++i)
+ {
+ ACE_INET_Addr &remote_addr = addresses[i];
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%t connecting to %s...\n",
+ hosts[i]));
+
+ // Create a new handler. It's what begin_connection() in TAO does.
+ Svc_Handler *svc_handler = 0;
+ result = this->base_connector_.connect (svc_handler,
+ remote_addr,
+ synch_options,
+ local_addr);
+ ACE_Event_Handler_var release_guard (svc_handler);
+
+ // Complete connection. It's what complete_connection() in TAO does.
+ // Not exactly but for the test it's enough.
+ while (this->reactor_.work_pending ())
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon,
+ this->reactor_lock_, -1);
+
+ if (this->reactor_.work_pending ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%t waiting for connection to %s...\n",
+ hosts[i]));
+
+ this->reactor_.owner (ACE_Thread::self ());
+
+ this->reactor_.handle_events ();
+ }
+ }
+
+ if (svc_handler->connected_)
+ {
+ this->reactor_.register_handler (svc_handler,
+ ACE_Event_Handler::READ_MASK);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%t connection for %s completed on handle %d.\n",
+ hosts[i],
+ svc_handler->get_handle ()));
+ // We are connected successfully. Close the connection.
+ this->reactor_.remove_handler (svc_handler->get_handle (),
+ ACE_Event_Handler::ALL_EVENTS_MASK |
+ ACE_Event_Handler::DONT_CALL);
+ }
+ else
+ {
+ // Connection didn't succeed. svc_handler will be deleted when
+ // we go out of the scope of this loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "%t connection for %s did not complete.\n",
+ hosts[i]));
+ }
+ }
+
+ if (--this->threads_ == 0)
+ {
+ // Close the connector.
+ this->base_connector_.close ();
+ }
+
+ delete[] addresses;
+
+ return 0;
+}
+
+void
+test (ACE_Reactor_Impl *reactor_impl)
+{
+ ACE_Reactor reactor (reactor_impl, true);
+
+ ACE_Thread_Mutex reactor_lock;
+ ACE_Thread_Manager thread_manager;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Starting %d connection threads...\n",
+ number_of_threads));
+
+ Connect_Thread connect_thread (thread_manager, reactor, reactor_lock);
+ result = connect_thread.activate (THR_NEW_LWP|THR_JOINABLE,
+ number_of_threads);
+ ACE_TEST_ASSERT (result == 0);
+
+ // Wait for threads to exit.
+ result = thread_manager.wait ();
+ ACE_TEST_ASSERT (result == 0);
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:d:f:g:k:lm:n:o:uz:"));
+
+ int cc;
+ while ((cc = get_opt ()) != -1)
+ {
+ switch (cc)
+ {
+ case 'a':
+ test_select_reactor = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'b':
+ test_tp_reactor = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'c':
+ test_wfmo_reactor = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'd':
+ test_dev_poll_reactor = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'f':
+ number_of_threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'z':
+ debug = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'u':
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("\nusage: %s \n\n")
+ ACE_TEXT ("\t[-a test Select Reactor] (defaults to %d)\n")
+ ACE_TEXT ("\t[-b test TP Reactor] (defaults to %d)\n")
+ ACE_TEXT ("\t[-c test WFMO Reactor] (defaults to %d)\n")
+ ACE_TEXT ("\t[-d test Dev Poll Reactor] (defaults to %d)\n")
+ ACE_TEXT ("\t[-f number of threads] (defaults to %d)\n")
+ ACE_TEXT ("\t[-z debug] (defaults to %d)\n")
+ ACE_TEXT ("\n"),
+ argv[0],
+ test_select_reactor,
+ test_tp_reactor,
+ test_wfmo_reactor,
+ test_dev_poll_reactor,
+ number_of_threads,
+ debug));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int
+run_main (int argc, ACE_TCHAR *argv[])
+{
+ ACE_START_TEST (ACE_TEXT ("MT_NonBlocking_Connect_Test"));
+
+ // Validate options.
+ result = parse_args (argc, argv);
+ if (result != 0)
+ return result;
+
+ if (test_select_reactor)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\n(%t) Testing Select Reactor....\n\n")));
+
+ test (new ACE_Select_Reactor);
+ }
+
+ if (test_tp_reactor)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\n(%t) Testing TP Reactor....\n\n")));
+
+ test (new ACE_TP_Reactor);
+ }
+
+#if defined (ACE_HAS_EVENT_POLL)
+
+ if (test_dev_poll_reactor)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\n(%t) Testing Dev Poll Reactor....\n\n")));
+
+ test (new ACE_Dev_Poll_Reactor);
+ }
+
+#endif
+
+#if defined (ACE_WIN32)
+
+ if (test_wfmo_reactor)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\n\n(%t) Testing WFMO Reactor....\n\n")));
+
+ test (new ACE_WFMO_Reactor);
+ }
+
+#endif /* ACE_WIN32 */
+
+ ACE_END_TEST;
+
+ return result;
+}
+
+#else /* ACE_HAS_THREADS */
+
+int
+run_main (int, ACE_TCHAR *[])
+{
+ ACE_START_TEST (ACE_TEXT ("MT_NonBlocking_Connect_Test"));
+
+ ACE_ERROR ((LM_INFO,
+ ACE_TEXT ("threads not supported on this platform\n")));
+
+ ACE_END_TEST;
+
+ return result;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/tests/NonBlocking_Conn_Test.cpp b/ACE/tests/NonBlocking_Conn_Test.cpp
index 7ca7df557a2..3161dea906a 100644
--- a/ACE/tests/NonBlocking_Conn_Test.cpp
+++ b/ACE/tests/NonBlocking_Conn_Test.cpp
@@ -35,10 +35,17 @@ static bool test_tp_reactor = true;
static bool test_wfmo_reactor = true;
static int result = 0;
-Svc_Handler::Svc_Handler (void)
+Svc_Handler::Svc_Handler (bool is_ref_counted)
: status_ (0),
- completion_counter_ (0)
+ completion_counter_ (0),
+ is_ref_counted_ (is_ref_counted)
{
+ if (this->is_ref_counted_)
+ {
+ // Enable reference counting on the event handler.
+ this->reference_counting_policy ().value (
+ ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
+ }
}
void
@@ -52,7 +59,7 @@ Svc_Handler::connection_status (Connection_Status &status,
int
Svc_Handler::open (void *)
{
- *this->status_ = SUCCEEDED;
+ *this->status_ = Svc_Handler::Conn_SUCCEEDED;
(*this->completion_counter_)++;
return 0;
@@ -61,18 +68,26 @@ Svc_Handler::open (void *)
int
Svc_Handler::handle_close (ACE_HANDLE handle, ACE_Reactor_Mask mask)
{
- *this->status_ = FAILED;
+ *this->status_ = Svc_Handler::Conn_FAILED;
(*this->completion_counter_)++;
- return ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>::handle_close (handle,
- mask);
+ // Only if there is no reference counting can call parent's
+ // handle_close() as it does plain 'delete this'.
+ if (!this->is_ref_counted_)
+ {
+ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> super;
+
+ return super::handle_close (handle, mask);
+ }
+
+ return 0;
}
typedef ACE_Connector<Svc_Handler, ACE_SOCK_CONNECTOR> CONNECTOR;
static const char* hosts[] = {
"www.russiantvguide.com:80",
- "www.pakarmy.gov.pk:80",
+ "news.bbc.co.uk:80",
"www.cnn.com:80",
"www.waca.com.au:80",
"www.uganda.co.ug:80",
@@ -80,15 +95,17 @@ static const char* hosts[] = {
"www.dre.vanderbilt.edu:80",
"www.dhm.gov.np:80",
"www.msn.com:80",
- "www.presidencymaldives.gov.mv:80" };
+ "www.presidencymaldives.gov.mv:80"
+};
static int number_of_connections = 0;
+static bool with_ref_counting = false;
void
test_connect (ACE_Reactor &reactor,
ACE_INET_Addr *addresses,
ACE_Synch_Options &synch_options,
- int complete_nonblocking_connections)
+ Svc_Handler::Completion_Status complete_nonblocking_connections)
{
CONNECTOR connector (&reactor);
@@ -104,7 +121,7 @@ test_connect (ACE_Reactor &reactor,
for (i = 0; i < number_of_connections; ++i)
{
svc_handlers[i] =
- new Svc_Handler;
+ new Svc_Handler (with_ref_counting);
svc_handlers[i]->connection_status (connection_status[i],
completion_counter);
@@ -119,7 +136,7 @@ test_connect (ACE_Reactor &reactor,
if (!synch_options[ACE_Synch_Options::USE_REACTOR])
ACE_ASSERT (completion_counter == number_of_connections);
- if (complete_nonblocking_connections)
+ if (complete_nonblocking_connections != Svc_Handler::Comp_NO)
{
while (completion_counter != number_of_connections)
{
@@ -139,10 +156,16 @@ test_connect (ACE_Reactor &reactor,
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("Connection to %s %s\n"),
buffer,
- connection_status[i] == Svc_Handler::SUCCEEDED ?
+ connection_status[i] == Svc_Handler::Conn_SUCCEEDED ?
ACE_TEXT("succeeded") : ACE_TEXT("failed")));
- if (connection_status[i] == Svc_Handler::SUCCEEDED)
+ ACE_Event_Handler_var release_guard;
+ if (with_ref_counting)
+ {
+ release_guard.reset (svc_handlers[i]);
+ }
+
+ if (connection_status[i] == Svc_Handler::Conn_SUCCEEDED)
{
svc_handlers[i]->close ();
}
@@ -171,10 +194,6 @@ test (ACE_Reactor_Impl *impl)
ACE_Reactor reactor (impl, 1);
- int complete_nonblocking_connections = 1;
- int dont_wait_for_nonblocking_connections = 0;
- int ignored = 99;
-
ACE_Synch_Options blocking_connect =
ACE_Synch_Options::defaults;
@@ -184,7 +203,7 @@ test (ACE_Reactor_Impl *impl)
test_connect (reactor,
addresses,
blocking_connect,
- ignored);
+ Svc_Handler::Comp_IGNORE);
blocking_connect.set (ACE_Synch_Options::USE_TIMEOUT,
ACE_Time_Value (0, 50 * 1000));
@@ -195,7 +214,7 @@ test (ACE_Reactor_Impl *impl)
test_connect (reactor,
addresses,
blocking_connect,
- ignored);
+ Svc_Handler::Comp_IGNORE);
ACE_Synch_Options nonblocking_connect
(ACE_Synch_Options::USE_REACTOR);
@@ -206,7 +225,7 @@ test (ACE_Reactor_Impl *impl)
test_connect (reactor,
addresses,
nonblocking_connect,
- complete_nonblocking_connections);
+ Svc_Handler::Comp_YES);
ACE_DEBUG ((LM_DEBUG,
"Non-blocking connections (without waiting for completions)...\n"));
@@ -214,7 +233,7 @@ test (ACE_Reactor_Impl *impl)
test_connect (reactor,
addresses,
nonblocking_connect,
- dont_wait_for_nonblocking_connections);
+ Svc_Handler::Comp_NO);
nonblocking_connect.set (ACE_Synch_Options::USE_REACTOR |
ACE_Synch_Options::USE_TIMEOUT,
@@ -226,7 +245,7 @@ test (ACE_Reactor_Impl *impl)
test_connect (reactor,
addresses,
nonblocking_connect,
- complete_nonblocking_connections);
+ Svc_Handler::Comp_YES);
delete[] addresses;
}
@@ -285,6 +304,13 @@ run_main (int argc, ACE_TCHAR *argv[])
ACE_DEBUG ((LM_DEBUG,
"Testing Select Reactor....\n"));
+ with_ref_counting = false;
+ test (new ACE_Select_Reactor);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing Select Reactor (ref counted)....\n"));
+
+ with_ref_counting = true;
test (new ACE_Select_Reactor);
}
@@ -293,6 +319,13 @@ run_main (int argc, ACE_TCHAR *argv[])
ACE_DEBUG ((LM_DEBUG,
"Testing TP Reactor....\n"));
+ with_ref_counting = false;
+ test (new ACE_TP_Reactor);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing TP Reactor (ref counted)....\n"));
+
+ with_ref_counting = true;
test (new ACE_TP_Reactor);
}
@@ -303,6 +336,13 @@ run_main (int argc, ACE_TCHAR *argv[])
ACE_DEBUG ((LM_DEBUG,
"Testing WFMO Reactor....\n"));
+ with_ref_counting = false;
+ test (new ACE_WFMO_Reactor);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing WFMO Reactor (ref counted)....\n"));
+
+ with_ref_counting = true;
test (new ACE_WFMO_Reactor);
}
@@ -312,4 +352,3 @@ run_main (int argc, ACE_TCHAR *argv[])
return result;
}
-
diff --git a/ACE/tests/NonBlocking_Conn_Test.h b/ACE/tests/NonBlocking_Conn_Test.h
index 77746238226..dc52f3fe694 100644
--- a/ACE/tests/NonBlocking_Conn_Test.h
+++ b/ACE/tests/NonBlocking_Conn_Test.h
@@ -33,11 +33,18 @@ public:
enum Connection_Status
{
- SUCCEEDED,
- FAILED
+ Conn_SUCCEEDED,
+ Conn_FAILED
};
- Svc_Handler (void);
+ enum Completion_Status
+ {
+ Comp_YES,
+ Comp_NO,
+ Comp_IGNORE
+ };
+
+ Svc_Handler (bool is_ref_counted = false);
void connection_status (Connection_Status &status,
int &completion_counter);
@@ -49,6 +56,7 @@ public:
Connection_Status *status_;
int *completion_counter_;
+ bool is_ref_counted_;
};
#endif /* NONBLOCKING_CONN_TEST_H */
diff --git a/ACE/tests/Process_Strategy_Test.cpp b/ACE/tests/Process_Strategy_Test.cpp
index a4f0d3123ba..74cbf0bfe12 100644
--- a/ACE/tests/Process_Strategy_Test.cpp
+++ b/ACE/tests/Process_Strategy_Test.cpp
@@ -441,8 +441,18 @@ int
Counting_Service::handle_close (ACE_HANDLE,
ACE_Reactor_Mask)
{
- // Done with another connection.
- connection_completed ();
+ // Count completed connections here only when the test is not in
+ // "process-per-connection" mode. In general, this should not be
+ // done here. Proper place for this is activate_svc_handler() but
+ // since only "process-per-connection" hooks into that function in
+ // other modes it's done here. The later creates a problem in
+ // "process-per-connection" mode since it calculates the same
+ // connection twice and as a result it cannot finalize gracefully.
+ if (OPTIONS::instance ()->concurrency_type () != Options::PROCESS)
+ {
+ // Done with another connection.
+ connection_completed ();
+ }
// Call down to base class
return ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>::handle_close ();
diff --git a/ACE/tests/run_test.lst b/ACE/tests/run_test.lst
index 9b94dbf38d5..1381a8dd0e7 100644
--- a/ACE/tests/run_test.lst
+++ b/ACE/tests/run_test.lst
@@ -114,6 +114,7 @@ Logging_Strategy_Test: !LynxOS !STATIC !ST
Manual_Event_Test
MEM_Stream_Test: !VxWorks !nsk !ACE_FOR_TAO !PHARLAP !QNX !LynxOS
MM_Shared_Memory_Test: !Unicos !VxWorks !nsk !ACE_FOR_TAO
+MT_NonBlocking_Connect_Test: !ST
MT_Reactor_Timer_Test
MT_Reactor_Upcall_Test: !nsk
MT_Reference_Counted_Event_Handler_Test: !OpenVMS_IA64Crash
diff --git a/ACE/tests/tests.mpc b/ACE/tests/tests.mpc
index d2eaafb48f0..032c6b53203 100644
--- a/ACE/tests/tests.mpc
+++ b/ACE/tests/tests.mpc
@@ -1630,6 +1630,15 @@ project(NonBlocking Conn Test) : acetest {
}
}
+project(MT NonBlocking Connect Test) : acetest {
+ exename = MT_NonBlocking_Connect_Test
+ Source_Files {
+ MT_NonBlocking_Connect_Test.cpp
+ }
+ Header_Files {
+ }
+}
+
project(Reference Counted Event Handler Test) : acetest {
exename = Reference_Counted_Event_Handler_Test
Source_Files {