|
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