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 | |