$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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));