diff options
Diffstat (limited to 'tests/Thread_Manager_Test.cpp')
-rw-r--r-- | tests/Thread_Manager_Test.cpp | 149 |
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; } |