Boost logo

Boost-Commit :

From: anthony_at_[hidden]
Date: 2007-10-26 03:33:23


Author: anthonyw
Date: 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
New Revision: 40472
URL: http://svn.boost.org/trac/boost/changeset/40472

Log:
added tests for cancellation
Text files modified:
   trunk/boost/thread/barrier.hpp | 4
   trunk/boost/thread/pthread/thread.hpp | 26 +++++++----
   trunk/boost/thread/win32/thread.hpp | 12 ++--
   trunk/libs/thread/src/pthread/thread.cpp | 89 ++++++++++++++++++++++++++++++++++++++-
   trunk/libs/thread/src/win32/thread.cpp | 4
   trunk/libs/thread/test/test_once.cpp | 6 +-
   trunk/libs/thread/test/test_thread.cpp | 54 +++++++++++++++++++++++
   7 files changed, 167 insertions(+), 28 deletions(-)

Modified: trunk/boost/thread/barrier.hpp
==============================================================================
--- trunk/boost/thread/barrier.hpp (original)
+++ trunk/boost/thread/barrier.hpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -11,7 +11,7 @@
 #include <boost/thread/detail/config.hpp>
 
 #include <boost/thread/mutex.hpp>
-#include <boost/thread/condition.hpp>
+#include <boost/thread/condition_variable.hpp>
 #include <string>
 #include <stdexcept>
 
@@ -48,7 +48,7 @@
 
     private:
         mutex m_mutex;
- condition m_cond;
+ condition_variable m_cond;
         unsigned int m_threshold;
         unsigned int m_count;
         unsigned int m_generation;

Modified: trunk/boost/thread/pthread/thread.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread.hpp (original)
+++ trunk/boost/thread/pthread/thread.hpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -92,18 +92,20 @@
         {
             boost::shared_ptr<thread_data_base> self;
             pthread_t thread_handle;
- boost::mutex done_mutex;
+ boost::mutex data_mutex;
             boost::condition_variable done_condition;
             bool done;
             bool join_started;
             bool joined;
             boost::detail::thread_exit_callback_node* thread_exit_callbacks;
             bool cancel_enabled;
+ bool cancel_requested;
 
             thread_data_base():
                 done(false),join_started(false),joined(false),
                 thread_exit_callbacks(0),
- cancel_enabled(true)
+ cancel_enabled(true),
+ cancel_requested(false)
             {}
             virtual ~thread_data_base()
             {}
@@ -203,19 +205,19 @@
             disable_cancellation& operator=(const disable_cancellation&);
             
             bool cancel_was_enabled;
- friend class enable_cancellation;
+ friend class restore_cancellation;
         public:
             disable_cancellation();
             ~disable_cancellation();
         };
 
- class enable_cancellation
+ class restore_cancellation
         {
- enable_cancellation(const enable_cancellation&);
- enable_cancellation& operator=(const enable_cancellation&);
+ restore_cancellation(const restore_cancellation&);
+ restore_cancellation& operator=(const restore_cancellation&);
         public:
- explicit enable_cancellation(disable_cancellation& d);
- ~enable_cancellation();
+ explicit restore_cancellation(disable_cancellation& d);
+ ~restore_cancellation();
         };
 
         inline thread::id get_id()
@@ -227,9 +229,13 @@
         bool BOOST_THREAD_DECL cancellation_enabled();
         bool BOOST_THREAD_DECL cancellation_requested();
 
- void BOOST_THREAD_DECL yield();
+ inline void yield()
+ {
+ thread::yield();
+ }
+
         template<typename TimeDuration>
- void sleep(TimeDuration const& rel_time)
+ inline void sleep(TimeDuration const& rel_time)
         {
             thread::sleep(get_system_time()+rel_time);
         }

Modified: trunk/boost/thread/win32/thread.hpp
==============================================================================
--- trunk/boost/thread/win32/thread.hpp (original)
+++ trunk/boost/thread/win32/thread.hpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -161,19 +161,19 @@
             disable_cancellation& operator=(const disable_cancellation&);
             
             bool cancel_was_enabled;
- friend class enable_cancellation;
+ friend class restore_cancellation;
         public:
             disable_cancellation();
             ~disable_cancellation();
         };
 
- class enable_cancellation
+ class restore_cancellation
         {
- enable_cancellation(const enable_cancellation&);
- enable_cancellation& operator=(const enable_cancellation&);
+ restore_cancellation(const restore_cancellation&);
+ restore_cancellation& operator=(const restore_cancellation&);
         public:
- explicit enable_cancellation(disable_cancellation& d);
- ~enable_cancellation();
+ explicit restore_cancellation(disable_cancellation& d);
+ ~restore_cancellation();
         };
 
         thread::id BOOST_THREAD_DECL get_id();

Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp (original)
+++ trunk/libs/thread/src/pthread/thread.cpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -94,7 +94,7 @@
 
                 tls_destructor(thread_info.get());
                 set_current_thread_data(0);
- boost::lock_guard<boost::mutex> lock(thread_info->done_mutex);
+ boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);
                 thread_info->done=true;
                 thread_info->done_condition.notify_all();
                 return 0;
@@ -147,7 +147,7 @@
             bool do_join=false;
             
             {
- unique_lock<mutex> lock(local_thread_info->done_mutex);
+ unique_lock<mutex> lock(local_thread_info->data_mutex);
                 while(!local_thread_info->done)
                 {
                     local_thread_info->done_condition.wait(lock);
@@ -171,7 +171,7 @@
                 void* result=0;
                 int const res=pthread_join(local_thread_info->thread_handle,&result);
                 BOOST_ASSERT(!res);
- lock_guard<mutex> lock(local_thread_info->done_mutex);
+ lock_guard<mutex> lock(local_thread_info->data_mutex);
                 local_thread_info->joined=true;
                 local_thread_info->done_condition.notify_all();
             }
@@ -200,7 +200,7 @@
         
         if(local_thread_info)
         {
- lock_guard<mutex> lock(local_thread_info->done_mutex);
+ lock_guard<mutex> lock(local_thread_info->data_mutex);
             if(!local_thread_info->join_started)
             {
                 int const res=pthread_detach(local_thread_info->thread_handle);
@@ -278,6 +278,87 @@
         }
     }
 
+ void thread::cancel()
+ {
+ boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ if(local_thread_info)
+ {
+ lock_guard<mutex> lk(local_thread_info->data_mutex);
+ local_thread_info->cancel_requested=true;
+ }
+ }
+
+
+ namespace this_thread
+ {
+ void cancellation_point()
+ {
+ boost::detail::thread_data_base* const thread_info=get_current_thread_data();
+ if(thread_info && thread_info->cancel_enabled)
+ {
+ lock_guard<mutex> lg(thread_info->data_mutex);
+ if(thread_info->cancel_requested)
+ {
+ thread_info->cancel_requested=false;
+ throw thread_cancelled();
+ }
+ }
+ }
+
+ bool cancellation_enabled()
+ {
+ boost::detail::thread_data_base* const thread_info=get_current_thread_data();
+ return thread_info && thread_info->cancel_enabled;
+ }
+
+ bool cancellation_requested()
+ {
+ boost::detail::thread_data_base* const thread_info=get_current_thread_data();
+ if(!thread_info)
+ {
+ return false;
+ }
+ else
+ {
+ lock_guard<mutex> lg(thread_info->data_mutex);
+ return thread_info->cancel_requested;
+ }
+ }
+
+ disable_cancellation::disable_cancellation():
+ cancel_was_enabled(cancellation_enabled())
+ {
+ if(cancel_was_enabled)
+ {
+ get_current_thread_data()->cancel_enabled=false;
+ }
+ }
+
+ disable_cancellation::~disable_cancellation()
+ {
+ if(get_current_thread_data())
+ {
+ get_current_thread_data()->cancel_enabled=cancel_was_enabled;
+ }
+ }
+
+ restore_cancellation::restore_cancellation(disable_cancellation& d)
+ {
+ if(d.cancel_was_enabled)
+ {
+ get_current_thread_data()->cancel_enabled=true;
+ }
+ }
+
+ restore_cancellation::~restore_cancellation()
+ {
+ if(get_current_thread_data())
+ {
+ get_current_thread_data()->cancel_enabled=false;
+ }
+ }
+ }
+
     thread_group::thread_group()
     {
     }

Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp (original)
+++ trunk/libs/thread/src/win32/thread.cpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -357,7 +357,7 @@
             }
         }
 
- enable_cancellation::enable_cancellation(disable_cancellation& d)
+ restore_cancellation::restore_cancellation(disable_cancellation& d)
         {
             if(d.cancel_was_enabled)
             {
@@ -365,7 +365,7 @@
             }
         }
         
- enable_cancellation::~enable_cancellation()
+ restore_cancellation::~restore_cancellation()
         {
             if(get_current_thread_data())
             {

Modified: trunk/libs/thread/test/test_once.cpp
==============================================================================
--- trunk/libs/thread/test/test_once.cpp (original)
+++ trunk/libs/thread/test/test_once.cpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -38,7 +38,7 @@
 
 void test_call_once()
 {
- unsigned const num_threads=100;
+ unsigned const num_threads=20;
     boost::thread_group group;
     
     for(unsigned i=0;i<num_threads;++i)
@@ -85,7 +85,7 @@
 
 void test_call_once_arbitrary_functor()
 {
- unsigned const num_threads=100;
+ unsigned const num_threads=20;
     boost::thread_group group;
 
     for(unsigned i=0;i<num_threads;++i)
@@ -134,7 +134,7 @@
 
 void test_call_once_retried_on_exception()
 {
- unsigned const num_threads=100;
+ unsigned const num_threads=20;
     boost::thread_group group;
 
     for(unsigned i=0;i<num_threads;++i)

Modified: trunk/libs/thread/test/test_thread.cpp
==============================================================================
--- trunk/libs/thread/test/test_thread.cpp (original)
+++ trunk/libs/thread/test/test_thread.cpp 2007-10-26 03:33:22 EDT (Fri, 26 Oct 2007)
@@ -8,6 +8,7 @@
 
 #include <boost/thread/thread.hpp>
 #include <boost/thread/xtime.hpp>
+#include <boost/bind.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -59,7 +60,7 @@
 void do_test_id_comparison()
 {
     boost::thread::id const self=boost::this_thread::get_id();
- boost::thread thrd(bind(&comparison_thread, self));
+ boost::thread thrd(boost::bind(&comparison_thread, self));
     thrd.join();
 }
 
@@ -68,6 +69,55 @@
     timed_test(&do_test_id_comparison, 1);
 }
 
+void cancellation_point_thread(boost::mutex* m,bool* failed)
+{
+ boost::mutex::scoped_lock lk(*m);
+ boost::this_thread::cancellation_point();
+ *failed=true;
+}
+
+void do_test_thread_cancels_at_cancellation_point()
+{
+ boost::mutex m;
+ bool failed=false;
+ boost::mutex::scoped_lock lk(m);
+ boost::thread thrd(boost::bind(&cancellation_point_thread,&m,&failed));
+ thrd.cancel();
+ lk.unlock();
+ thrd.join();
+ BOOST_CHECK(!failed);
+}
+
+void test_thread_cancels_at_cancellation_point()
+{
+ timed_test(&do_test_thread_cancels_at_cancellation_point, 1);
+}
+
+void disabled_cancellation_point_thread(boost::mutex* m,bool* failed)
+{
+ boost::mutex::scoped_lock lk(*m);
+ boost::this_thread::disable_cancellation dc;
+ boost::this_thread::cancellation_point();
+ *failed=false;
+}
+
+void do_test_thread_no_cancel_if_cancels_disabled_at_cancellation_point()
+{
+ boost::mutex m;
+ bool failed=true;
+ boost::mutex::scoped_lock lk(m);
+ boost::thread thrd(boost::bind(&disabled_cancellation_point_thread,&m,&failed));
+ thrd.cancel();
+ lk.unlock();
+ thrd.join();
+ BOOST_CHECK(!failed);
+}
+
+void test_thread_no_cancel_if_cancels_disabled_at_cancellation_point()
+{
+ timed_test(&do_test_thread_no_cancel_if_cancels_disabled_at_cancellation_point, 1);
+}
+
 boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
 {
     boost::unit_test_framework::test_suite* test =
@@ -76,6 +126,8 @@
     test->add(BOOST_TEST_CASE(test_sleep));
     test->add(BOOST_TEST_CASE(test_creation));
     test->add(BOOST_TEST_CASE(test_id_comparison));
+ test->add(BOOST_TEST_CASE(test_thread_cancels_at_cancellation_point));
+ test->add(BOOST_TEST_CASE(test_thread_no_cancel_if_cancels_disabled_at_cancellation_point));
 
     return test;
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk