diff options
author | Steve Huston <shuston@riverace.com> | 2006-01-31 22:14:22 +0000 |
---|---|---|
committer | Steve Huston <shuston@riverace.com> | 2006-01-31 22:14:22 +0000 |
commit | 1349ba35ad51fafaad7ccc0d0079063401e6416e (patch) | |
tree | f82aff5ff78306ee5c22d2ff218e84a1e01de9d9 | |
parent | 96ea583ca55755b27a95166c87f5b148285215fc (diff) | |
download | ATCD-1349ba35ad51fafaad7ccc0d0079063401e6416e.tar.gz |
ChangeLogTag:Tue Jan 31 22:08:57 UTC 2006 Steve Huston <shuston@riverace.com>
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | ace/Barrier.cpp | 48 | ||||
-rw-r--r-- | ace/Barrier.h | 10 | ||||
-rw-r--r-- | tests/Barrier_Test.cpp | 39 |
4 files changed, 100 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog index 1401cae667c..30279fbe19a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Tue Jan 31 22:08:57 UTC 2006 Steve Huston <shuston@riverace.com> + + * ace/Barrier.{h cpp}: Added a new shutdown () method which aborts all + waiting on the barrier. Thanks to John Lilley <jlilley at datalever + dot com> for contributing this method. + Also note that the wait() method can now return -1 with errno + ESHUTDOWN if the barrier is shut down while waiting for it. + + * tests/Barrier_Test.cpp: Added a test for barrier shutdown. + Tue Jan 31 21:34:34 UTC 2006 William Otte <wotte@dre.vanderbilt.edu> * bin/ciao_tests.lst diff --git a/ace/Barrier.cpp b/ace/Barrier.cpp index 0f8ffeb61eb..739e249cd76 100644 --- a/ace/Barrier.cpp +++ b/ace/Barrier.cpp @@ -9,6 +9,7 @@ #endif /* __ACE_INLINE__ */ #include "ace/Guard_T.h" +#include "ace/OS_NS_errno.h" #if defined (ACE_HAS_DUMP) # include "ace/Log_Msg.h" @@ -73,7 +74,7 @@ ACE_Barrier::ACE_Barrier (unsigned int count, sub_barrier_1_ (count, lock_, name, arg), sub_barrier_2_ (count, lock_, name, arg) { -// ACE_TRACE ("ACE_Barrier::ACE_Barrier"); + ACE_TRACE ("ACE_Barrier::ACE_Barrier"); this->sub_barrier_[0] = &this->sub_barrier_1_; this->sub_barrier_[1] = &this->sub_barrier_2_; } @@ -81,7 +82,7 @@ ACE_Barrier::ACE_Barrier (unsigned int count, int ACE_Barrier::wait (void) { -// ACE_TRACE ("ACE_Barrier::wait"); + ACE_TRACE ("ACE_Barrier::wait"); ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); ACE_Sub_Barrier *sbp = @@ -89,14 +90,18 @@ ACE_Barrier::wait (void) // Check for shutdown... if (sbp == 0) - return -1; + { + errno = ESHUTDOWN; + return -1; + } + + int retval = 0; if (sbp->running_threads_ == 1) { // We're the last running thread, so swap generations and tell // all the threads waiting on the barrier to continue on their // way. - sbp->running_threads_ = this->count_; // Swap generations. this->current_generation_ = 1 - this->current_generation_; @@ -109,8 +114,43 @@ ACE_Barrier::wait (void) // Block until all the other threads wait(). while (sbp->running_threads_ != this->count_) sbp->barrier_finished_.wait (); + + // We're awake and the count has completed. See if it completed + // because all threads hit the barrier, or because the barrier + // was shut down. + if (this->sub_barrier_[this->current_generation_] == 0) + { + errno = ESHUTDOWN; + retval = -1; + } + } + + return retval; +} + +int +ACE_Barrier::shutdown (void) +{ + ACE_TRACE ("ACE_Barrier::shutdown"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + ACE_Sub_Barrier *sbp = + this->sub_barrier_[this->current_generation_]; + + // Check for shutdown... + if (sbp == 0) + { + errno = ESHUTDOWN; + return -1; } + // Flag the shutdown + this->sub_barrier_[0] = 0; + this->sub_barrier_[1] = 0; + // Tell all the threads waiting on the barrier to continue on their way. + sbp->running_threads_ = this->count_; + sbp->barrier_finished_.broadcast (); + return 0; } diff --git a/ace/Barrier.h b/ace/Barrier.h index 56532801a65..84d97e836b9 100644 --- a/ace/Barrier.h +++ b/ace/Barrier.h @@ -106,8 +106,18 @@ public: /// Block the caller until all @c count threads have called @c wait and /// then allow all the caller threads to continue in parallel. + /// + /// @retval 0 after successfully waiting for all threads to wait. -1 if + /// an error occurs or the barrier is shut down (@sa shutdown ()). int wait (void); + /// Shut the barrier down, aborting the wait of all waiting threads. + /// Any threads waiting on the barrier when it is shut down will return with + /// value -1, errno ESHUTDOWN. + /// + /// @retval 0 for success, -1 if already shut down. + int shutdown (void); + /// Dump the state of an object. void dump (void) const; diff --git a/tests/Barrier_Test.cpp b/tests/Barrier_Test.cpp index ce2fa29cb5b..2af15dfb66d 100644 --- a/tests/Barrier_Test.cpp +++ b/tests/Barrier_Test.cpp @@ -45,7 +45,7 @@ struct Tester_Args // for all other threads to complete this iteration. static void * -tester (Tester_Args *args) +wait_tester (Tester_Args *args) { for (int iterations = 1; iterations <= args->n_iterations_; @@ -55,12 +55,30 @@ tester (Tester_Args *args) iterations)); // Block until all other threads have waited, then continue. - args->tester_barrier_.wait (); + if (args->tester_barrier_.wait () != 0) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), + ACE_TEXT ("wait failed"))); } return 0; } +// Wait on the barrier, expecting it to be shut down before completing +// the wait. + +static void * +shut_tester (Tester_Args *args) +{ + if (args->tester_barrier_.wait () == 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%t) wait succeeded, should have shut down\n"))); + else if (errno != ESHUTDOWN) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%t) wait failed, expecting ESHUTDOWN, %p\n"), + ACE_TEXT ("got"))); + return 0; +} + #endif /* ACE_HAS_THREADS */ int @@ -85,7 +103,7 @@ run_main (int, ACE_TCHAR *[]) if (ACE_Thread_Manager::instance ()->spawn_n (n_threads, - (ACE_THR_FUNC) tester, + (ACE_THR_FUNC) wait_tester, (void *) &args, THR_NEW_LWP | THR_JOINABLE) == -1) @@ -95,6 +113,21 @@ run_main (int, ACE_TCHAR *[]) ACE_Thread_Manager::instance ()->wait (); } + // Now test ACE_Barrier shutdown. Set up a barrier for n_threads, and start + // n_threads - 1 threads to wait, then shut the barrier down. + ACE_Barrier shut_barrier (n_threads); + Tester_Args shut_args (shut_barrier, 1); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Starting shutdown test threads\n"))); + if (ACE_Thread_Manager::instance ()->spawn_n + (n_threads - 1, + (ACE_THR_FUNC) shut_tester, + (void *) &shut_args, + THR_NEW_LWP | THR_JOINABLE) == -1) + ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn_n")), 1); + + shut_barrier.shutdown (); + ACE_Thread_Manager::instance ()->wait (); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("test done\n"))); #else ACE_ERROR ((LM_INFO, |