1 // Distributed under the Boost Software License, Version 1.0. (See
2 // accompanying file LICENSE_1_0.txt or copy at
3 // http://www.boost.org/LICENSE_1_0.txt)
4 // (C) Copyright 2007 Anthony Williams
5 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
6 
7 #ifndef BOOST_THREAD_LOCKABLE_TRAITS_HPP
8 #define BOOST_THREAD_LOCKABLE_TRAITS_HPP
9 
10 #include <boost/thread/detail/config.hpp>
11 
12 #include <boost/assert.hpp>
13 #include <boost/detail/workaround.hpp>
14 #include <boost/type_traits/is_class.hpp>
15 
16 #include <boost/config/abi_prefix.hpp>
17 
18 // todo make use of integral_constant, true_type and false_type
19 
20 namespace boost
21 {
22   namespace sync
23   {
24 
25 #if defined(BOOST_NO_SFINAE) ||                           \
26     BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
27     BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
28 #if ! defined BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
29 #define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
30 #endif
31 #endif
32 
33 #ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
34     namespace detail
35     {
36 #define BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(member_name)                     \
37         template<typename T, bool=boost::is_class<T>::value>            \
38         struct has_member_called_##member_name                          \
39         {                                                               \
40             BOOST_STATIC_CONSTANT(bool, value=false);                   \
41         };                                                              \
42                                                                         \
43         template<typename T>                                            \
44         struct has_member_called_##member_name<T,true>                  \
45         {                                                               \
46             typedef char true_type;                                     \
47             struct false_type                                           \
48             {                                                           \
49                 true_type dummy[2];                                     \
50             };                                                          \
51                                                                         \
52             struct fallback { int member_name; };                       \
53             struct derived:                                             \
54                 T, fallback                                             \
55             {                                                           \
56                 derived();                                              \
57             };                                                          \
58                                                                         \
59             template<int fallback::*> struct tester;                    \
60                                                                         \
61             template<typename U>                                        \
62                 static false_type has_member(tester<&U::member_name>*); \
63             template<typename U>                                        \
64                 static true_type has_member(...);                       \
65                                                                         \
66             BOOST_STATIC_CONSTANT(                                      \
67                 bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \
68         }
69 
70       BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock)
71 ;      BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock);
72       BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock);
73 
74       template<typename T,bool=has_member_called_lock<T>::value >
75       struct has_member_lock
76       {
77         BOOST_STATIC_CONSTANT(bool, value=false);
78       };
79 
80       template<typename T>
81       struct has_member_lock<T,true>
82       {
83         typedef char true_type;
84         struct false_type
85         {
86           true_type dummy[2];
87         };
88 
89         template<typename U,typename V>
90         static true_type has_member(V (U::*)());
91         template<typename U>
92         static false_type has_member(U);
93 
94         BOOST_STATIC_CONSTANT(
95             bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
96       };
97 
98       template<typename T,bool=has_member_called_unlock<T>::value >
99       struct has_member_unlock
100       {
101         BOOST_STATIC_CONSTANT(bool, value=false);
102       };
103 
104       template<typename T>
105       struct has_member_unlock<T,true>
106       {
107         typedef char true_type;
108         struct false_type
109         {
110           true_type dummy[2];
111         };
112 
113         template<typename U,typename V>
114         static true_type has_member(V (U::*)());
115         template<typename U>
116         static false_type has_member(U);
117 
118         BOOST_STATIC_CONSTANT(
119             bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
120       };
121 
122       template<typename T,bool=has_member_called_try_lock<T>::value >
123       struct has_member_try_lock
124       {
125         BOOST_STATIC_CONSTANT(bool, value=false);
126       };
127 
128       template<typename T>
129       struct has_member_try_lock<T,true>
130       {
131         typedef char true_type;
132         struct false_type
133         {
134           true_type dummy[2];
135         };
136 
137         template<typename U>
138         static true_type has_member(bool (U::*)());
139         template<typename U>
140         static false_type has_member(U);
141 
142         BOOST_STATIC_CONSTANT(
143             bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
144       };
145 
146     }
147 
148     template<typename T>
149     struct is_basic_lockable
150     {
151       BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
152           detail::has_member_unlock<T>::value);
153     };
154     template<typename T>
155     struct is_lockable
156     {
157       BOOST_STATIC_CONSTANT(bool, value =
158           is_basic_lockable<T>::value &&
159           detail::has_member_try_lock<T>::value);
160     };
161 
162 #else
163     template<typename T>
164     struct is_basic_lockable
165     {
166       BOOST_STATIC_CONSTANT(bool, value = false);
167     };
168     template<typename T>
169     struct is_lockable
170     {
171       BOOST_STATIC_CONSTANT(bool, value = false);
172     };
173 #endif
174 
175     template<typename T>
176     struct is_recursive_mutex_sur_parole
177     {
178       BOOST_STATIC_CONSTANT(bool, value = false);
179     };
180     template<typename T>
181     struct is_recursive_mutex_sur_parolle : is_recursive_mutex_sur_parole<T>
182     {
183     };
184 
185     template<typename T>
186     struct is_recursive_basic_lockable
187     {
188       BOOST_STATIC_CONSTANT(bool, value = is_basic_lockable<T>::value &&
189           is_recursive_mutex_sur_parolle<T>::value);
190     };
191     template<typename T>
192     struct is_recursive_lockable
193     {
194       BOOST_STATIC_CONSTANT(bool, value = is_lockable<T>::value &&
195           is_recursive_mutex_sur_parolle<T>::value);
196     };
197   }
198   template<typename T>
199   struct is_mutex_type
200   {
201     BOOST_STATIC_CONSTANT(bool, value = sync::is_lockable<T>::value);
202   };
203 
204 }
205 #include <boost/config/abi_suffix.hpp>
206 
207 #endif
208