summaryrefslogtreecommitdiff
path: root/tests/Thread_Manager_Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Thread_Manager_Test.cpp')
-rw-r--r--tests/Thread_Manager_Test.cpp149
1 files changed, 61 insertions, 88 deletions
diff --git a/tests/Thread_Manager_Test.cpp b/tests/Thread_Manager_Test.cpp
index a739a8aa180..366d72a2900 100644
--- a/tests/Thread_Manager_Test.cpp
+++ b/tests/Thread_Manager_Test.cpp
@@ -32,56 +32,28 @@ USELIB("..\ace\aced.lib");
#if defined (ACE_HAS_THREADS)
-// Each thread keeps track of whether it has been signalled by using a
-// global array. It must be dynamically allocated to allow sizing at
-// runtime, based on the number of threads.
-static ACE_thread_t *signalled = 0;
-static u_int n_threads = ACE_MAX_THREADS;
-
-// Helper function that looks for an existing entry in the signalled
-// array. Also finds the position of the first unused entry in the
-// array, and updates if requested with the t_id.
-extern "C"
-int
-been_signalled (const ACE_thread_t t_id, const u_int update = 0)
-{
- u_int unused_slot = n_threads;
- for (u_int i = 0; i < n_threads; ++i)
- {
- if (ACE_OS::thr_equal (signalled[i], t_id))
- // Already signalled.
- return 1;
-
- if (update &&
- unused_slot == n_threads &&
- ACE_OS::thr_equal (signalled[i], ACE_OS::NULL_thread))
- unused_slot = i;
- }
+#include "Thread_Manager_Test.h"
- if (update && unused_slot < n_threads)
- // Update the array using the first unused_slot.
- signalled[unused_slot] = t_id;
-
- return 0;
-}
+// Each thread keeps track of whether it has been signaled within a
+// separate TSS entry. See comment below about why it's allocated
+// dynamically.
+static ACE_TSS<Signal_Catcher> *signal_catcher = 0;
// Synchronize starts of threads, so that they all start before the
-// main thread cancels them. To avoid creating a static object, it is
-// dynamically allocated, before spawning any threads.
-static ACE_Barrier *thread_start = 0;
+// main thread cancels them. To avoid creating a static object, it
+// is dynamically allocated, before spawning any threads.
+static ACE_Barrier *thread_start;
-extern "C"
-void
-handler (int /* signum */)
+extern "C" void
+handler (int signum)
{
- if (signalled)
+ if (signal_catcher)
{
- // No printout here, to be safe. Signal handlers must not
- // acquire locks, etc.
- const ACE_thread_t t_id = ACE_OS::thr_self ();
-
- // Update the signalled indication.
- (void) been_signalled (t_id, 1u /* update */);
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%t) received signal %d, signaled = %d\n"),
+ signum,
+ (*signal_catcher)->signaled ()));
+ (*signal_catcher)->signaled (1);
}
}
@@ -94,8 +66,25 @@ worker (int iterations)
#endif /* VXWORKS */
#if !defined (ACE_LACKS_UNIX_SIGNALS)
- // Cache this thread's ID.
- const ACE_thread_t t_id = ACE_OS::thr_self ();
+ // Cache a pointer to this thread's Signal_Catcher. That way, we
+ // try to avoid dereferencing signal_catcher below in a thread that
+ // hasn't terminated when main exits. That shouldn't happen, but it
+ // seems to on Linux and LynxOS.
+ if (!signal_catcher)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%t) (worker): signal catcher is 0!!!!\n")));
+ return (void *) -1;
+ }
+
+ Signal_Catcher *my_signal_catcher = *signal_catcher;
+
+ if (my_signal_catcher == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%t) (worker): *signal catcher is 0!!!!\n")));
+ return (void *) -1;
+ }
ACE_Thread_Manager *thr_mgr = ACE_Thread_Manager::instance ();
#endif /* ! ACE_LACKS_UNIX_SIGNAL */
@@ -111,21 +100,15 @@ worker (int iterations)
if ((i % 1000) == 0)
{
#if !defined (ACE_LACKS_UNIX_SIGNALS)
- if (been_signalled (t_id))
- {
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%t) had received signal\n")));
-
+ if (my_signal_catcher->signaled () > 0 &&
// Only test for cancellation after we've been signaled,
// to avoid race conditions for suspend() and resume().
- if (thr_mgr->testcancel (ACE_Thread::self ()) != 0)
- {
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%t) has been cancelled "
- "before iteration %d!\n"),
- i));
- break;
- }
+ thr_mgr->testcancel (ACE_Thread::self ()) != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%t) has been cancelled before iteration %d!\n"),
+ i));
+ break;
}
#endif /* ! ACE_LACKS_UNIX_SIGNAL */
ACE_OS::sleep (1);
@@ -136,28 +119,30 @@ worker (int iterations)
return 0;
}
+static const int DEFAULT_THREADS = ACE_MAX_THREADS;
static const int DEFAULT_ITERATIONS = 10000;
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+template class ACE_TSS<Signal_Catcher>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_TSS<Signal_Catcher>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
#endif /* ACE_HAS_THREADS */
int
main (int, ASYS_TCHAR *[])
{
ACE_START_TEST (ASYS_TEXT ("Thread_Manager_Test"));
- int status = 0;
#if defined (ACE_HAS_THREADS)
+ int n_threads = DEFAULT_THREADS;
int n_iterations = DEFAULT_ITERATIONS;
- u_int i;
-
- // Dynamically allocate signalled so that we can control when it
- // gets deleted. Specifically, we need to delete it before the main
- // thread's TSS is cleaned up.
- ACE_NEW_RETURN (signalled, ACE_thread_t[n_threads], 1);
- // Initialize each ACE_thread_t to avoid Purify UMR's.
- for (i = 0; i < n_threads; ++i)
- signalled[i] = ACE_OS::NULL_thread;
+ // Dynamically allocate signal_catcher so that we can control when
+ // it gets deleted. Specifically, we need to delete it before the
+ // main thread's TSS is cleaned up.
+ ACE_NEW_RETURN (signal_catcher, ACE_TSS<Signal_Catcher>, 1);
// And similarly, dynamically allocate the thread_start barrier.
ACE_NEW_RETURN (thread_start, ACE_Barrier (n_threads + 1), -1);
@@ -177,6 +162,8 @@ main (int, ASYS_TCHAR *[])
size_t *stack_size;
ACE_NEW_RETURN (stack_size, size_t[n_threads], -1);
+ int i;
+
for (i = 0; i < n_threads; ++i)
{
if (i < n_threads - 1)
@@ -251,7 +238,7 @@ main (int, ASYS_TCHAR *[])
ACE_ASSERT (errno == ENOTSUP);
#endif /* ACE_HAS_WTHREADS */
- // Wait and then cancel all the threads.
+ // Wait for 1 more second and then cancel all the threads.
ACE_OS::sleep (ACE_Time_Value (1));
ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) cancelling group\n")));
@@ -259,21 +246,7 @@ main (int, ASYS_TCHAR *[])
ACE_ASSERT (thr_mgr->cancel_grp (grp_id) != -1);
// Perform a barrier wait until all the threads have shut down.
- // But, wait for a limited time because sometimes the test hangs
- // on SunOS 5.5.1 and 5.7.
- const ACE_Time_Value max_wait (60);
- const ACE_Time_Value wait_time (ACE_OS::gettimeofday () + max_wait);
- if (thr_mgr->wait (&wait_time) == -1)
- {
- if (errno == ETIME)
- ACE_ERROR ((LM_ERROR,
- ASYS_TEXT ("maximum wait time of %d msec exceeded\n"),
- max_wait.msec ()));
- else
- ACE_OS::perror ("wait");
-
- status = -1;
- }
+ ACE_ASSERT (thr_mgr->wait () != -1);
ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) main thread finished\n")));
@@ -290,8 +263,8 @@ main (int, ASYS_TCHAR *[])
delete thread_start;
thread_start = 0;
- delete [] signalled;
- signalled = 0;
+ delete signal_catcher;
+ signal_catcher = 0;
#else
ACE_ERROR ((LM_INFO,
@@ -299,5 +272,5 @@ main (int, ASYS_TCHAR *[])
#endif /* ACE_HAS_THREADS */
ACE_END_TEST;
- return status;
+ return 0;
}