Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62562 - in trunk: boost/thread boost/thread/win32 libs/thread/test
From: anthony_at_[hidden]
Date: 2010-06-08 08:06:04


Author: anthonyw
Date: 2010-06-08 08:06:03 EDT (Tue, 08 Jun 2010)
New Revision: 62562
URL: http://svn.boost.org/trac/boost/changeset/62562

Log:
Updated tests for mutex members to handle range-based lock() and try_lock(), and fix issue #2704
Text files modified:
   trunk/boost/thread/locks.hpp | 181 +++++++++++++++++++++++++++++++++++++--
   trunk/boost/thread/win32/mutex.hpp | 8 +
   trunk/libs/thread/test/test_generic_locks.cpp | 77 ++++++++++++++++
   3 files changed, 248 insertions(+), 18 deletions(-)

Modified: trunk/boost/thread/locks.hpp
==============================================================================
--- trunk/boost/thread/locks.hpp (original)
+++ trunk/boost/thread/locks.hpp 2010-06-08 08:06:03 EDT (Tue, 08 Jun 2010)
@@ -11,6 +11,7 @@
 #include <iterator>
 #include <boost/thread/thread_time.hpp>
 #include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_class.hpp>
 
 #include <boost/config/abi_prefix.hpp>
 
@@ -27,41 +28,193 @@
 #ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
     namespace detail
     {
- template<typename T>
+#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \
+ template<typename T, bool=boost::is_class<T>::value> \
+ struct has_member_called_##member_name \
+ { \
+ BOOST_STATIC_CONSTANT(bool, value=false); \
+ }; \
+ \
+ template<typename T> \
+ struct has_member_called_##member_name<T,true> \
+ { \
+ typedef char true_type; \
+ struct false_type \
+ { \
+ true_type dummy[2]; \
+ }; \
+ \
+ struct fallback { int member_name; }; \
+ struct derived: \
+ T, fallback \
+ {}; \
+ \
+ template<int fallback::*> struct tester; \
+ \
+ template<typename U> \
+ static false_type has_member(tester<&U::member_name>*); \
+ template<typename U> \
+ static true_type has_member(...); \
+ \
+ BOOST_STATIC_CONSTANT( \
+ bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
+ }
+
+ BOOST_DEFINE_HAS_MEMBER_CALLED(lock);
+ BOOST_DEFINE_HAS_MEMBER_CALLED(unlock);
+ BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock);
+
+
+ // template<typename T, bool=boost::is_class<T>::value>
+ // struct has_member_called_lock
+ // {
+ // BOOST_STATIC_CONSTANT(bool, value=false);
+ // };
+
+ // template<typename T>
+ // struct has_member_called_lock<T,true>
+ // {
+ // typedef char true_type;
+ // struct false_type
+ // {
+ // true_type dummy[2];
+ // };
+
+ // struct fallback { int lock; };
+ // struct derived:
+ // T, fallback
+ // {};
+
+ // template<int fallback::*> struct tester;
+
+ // template<typename U>
+ // static false_type has_member(tester<&U::lock>*);
+ // template<typename U>
+ // static true_type has_member(...);
+
+ // BOOST_STATIC_CONSTANT(
+ // bool, value=sizeof(has_member<derived>(0))==sizeof(true_type));
+ // };
+
+ // template<typename T, bool=boost::is_class<T>::value>
+ // struct has_member_called_unlock
+ // {
+ // BOOST_STATIC_CONSTANT(bool, value=false);
+ // };
+
+ // template<typename T>
+ // struct has_member_called_unlock<T,true>
+ // {
+ // typedef char true_type;
+ // struct false_type
+ // {
+ // true_type dummy[2];
+ // };
+
+ // struct fallback { int unlock; };
+ // struct derived:
+ // T, fallback
+ // {};
+
+ // template<int fallback::*> struct tester;
+
+ // template<typename U>
+ // static false_type has_member(tester<&U::unlock>*);
+ // template<typename U>
+ // static true_type has_member(...);
+
+ // BOOST_STATIC_CONSTANT(
+ // bool, value=sizeof(has_member<derived>(0))==sizeof(true_type));
+ // };
+
+ // template<typename T, bool=boost::is_class<T>::value>
+ // struct has_member_called_try_lock
+ // {
+ // BOOST_STATIC_CONSTANT(bool, value=false);
+ // };
+
+ // template<typename T>
+ // struct has_member_called_try_lock<T,true>
+ // {
+ // typedef char true_type;
+ // struct false_type
+ // {
+ // true_type dummy[2];
+ // };
+
+ // struct fallback { int try_lock; };
+ // struct derived:
+ // T, fallback
+ // {};
+
+ // template<int fallback::*> struct tester;
+
+ // template<typename U>
+ // static false_type has_member(tester<&U::try_lock>*);
+ // template<typename U>
+ // static true_type has_member(...);
+
+ // BOOST_STATIC_CONSTANT(
+ // bool, value=sizeof(has_member<derived>(0))==sizeof(true_type));
+ // };
+
+ template<typename T,bool=has_member_called_lock<T>::value >
         struct has_member_lock
         {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_lock<T,true>
+ {
             typedef char true_type;
             struct false_type
             {
                 true_type dummy[2];
             };
             
+ template<typename U,typename V>
+ static true_type has_member(V (U::*)());
             template<typename U>
- static true_type has_member(U*,void (U::*dummy)()=&U::lock);
- static false_type has_member(void*);
+ static false_type has_member(U);
             
- BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock<T>::has_member((T*)NULL))==sizeof(true_type));
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
         };
-
- template<typename T>
+
+ template<typename T,bool=has_member_called_unlock<T>::value >
         struct has_member_unlock
         {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_unlock<T,true>
+ {
             typedef char true_type;
             struct false_type
             {
                 true_type dummy[2];
             };
             
+ template<typename U,typename V>
+ static true_type has_member(V (U::*)());
             template<typename U>
- static true_type has_member(U*,void (U::*dummy)()=&U::unlock);
- static false_type has_member(void*);
+ static false_type has_member(U);
             
- BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock<T>::has_member((T*)NULL))==sizeof(true_type));
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
         };
         
- template<typename T>
+ template<typename T,bool=has_member_called_try_lock<T>::value >
         struct has_member_try_lock
         {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct has_member_try_lock<T,true>
+ {
             typedef char true_type;
             struct false_type
             {
@@ -69,10 +222,12 @@
             };
             
             template<typename U>
- static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock);
- static false_type has_member(void*);
+ static true_type has_member(bool (U::*)());
+ template<typename U>
+ static false_type has_member(U);
             
- BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock<T>::has_member((T*)NULL))==sizeof(true_type));
+ BOOST_STATIC_CONSTANT(
+ bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
         };
 
     }

Modified: trunk/boost/thread/win32/mutex.hpp
==============================================================================
--- trunk/boost/thread/win32/mutex.hpp (original)
+++ trunk/boost/thread/win32/mutex.hpp 2010-06-08 08:06:03 EDT (Tue, 08 Jun 2010)
@@ -20,9 +20,11 @@
     }
 
     class mutex:
- boost::noncopyable,
         public ::boost::detail::underlying_mutex
     {
+ private:
+ mutex(mutex const&);
+ mutex& operator=(mutex const&);
     public:
         mutex()
         {
@@ -40,9 +42,11 @@
     typedef mutex try_mutex;
 
     class timed_mutex:
- boost::noncopyable,
         public ::boost::detail::basic_timed_mutex
     {
+ private:
+ timed_mutex(timed_mutex const&);
+ timed_mutex& operator=(timed_mutex const&);
     public:
         timed_mutex()
         {

Modified: trunk/libs/thread/test/test_generic_locks.cpp
==============================================================================
--- trunk/libs/thread/test/test_generic_locks.cpp (original)
+++ trunk/libs/thread/test/test_generic_locks.cpp 2010-06-08 08:06:03 EDT (Tue, 08 Jun 2010)
@@ -296,11 +296,81 @@
     }
 }
 
-void test_lock_ten_in_range()
+class dummy_iterator:
+ public std::iterator<std::forward_iterator_tag,
+ dummy_mutex>
 {
- unsigned const num_mutexes=10;
+private:
+ dummy_mutex* p;
+public:
+ explicit dummy_iterator(dummy_mutex* p_):
+ p(p_)
+ {}
+
+ bool operator==(dummy_iterator const& other) const
+ {
+ return p==other.p;
+ }
+
+ bool operator!=(dummy_iterator const& other) const
+ {
+ return p!=other.p;
+ }
+
+ bool operator<(dummy_iterator const& other) const
+ {
+ return p<other.p;
+ }
+
+ dummy_mutex& operator*() const
+ {
+ return *p;
+ }
+
+ dummy_mutex* operator->() const
+ {
+ return p;
+ }
+
+ dummy_iterator operator++(int)
+ {
+ dummy_iterator temp(*this);
+ ++p;
+ return temp;
+ }
+
+ dummy_iterator& operator++()
+ {
+ ++p;
+ return *this;
+ }
+
+};
+
+
+void test_lock_five_in_range_custom_iterator()
+{
+ unsigned const num_mutexes=5;
     dummy_mutex mutexes[num_mutexes];
 
+ boost::lock(dummy_iterator(mutexes),dummy_iterator(mutexes+num_mutexes));
+
+ for(unsigned i=0;i<num_mutexes;++i)
+ {
+ BOOST_CHECK(mutexes[i].is_locked);
+ }
+}
+
+class dummy_mutex2:
+ public dummy_mutex
+{};
+
+
+void test_lock_ten_in_range_inherited_mutex()
+{
+ unsigned const num_mutexes=10;
+ dummy_mutex2 mutexes[num_mutexes];
+
     boost::lock(mutexes,mutexes+num_mutexes);
     
     for(unsigned i=0;i<num_mutexes;++i)
@@ -510,7 +580,8 @@
     test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));
     test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));
     test->add(BOOST_TEST_CASE(&test_lock_five_in_range));
- test->add(BOOST_TEST_CASE(&test_lock_ten_in_range));
+ test->add(BOOST_TEST_CASE(&test_lock_five_in_range_custom_iterator));
+ test->add(BOOST_TEST_CASE(&test_lock_ten_in_range_inherited_mutex));
     test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));
     test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));
     test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));


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