]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/atomic/test/api_test_helpers.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / atomic / test / api_test_helpers.hpp
1 // Copyright (c) 2011 Helge Bahmann
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef BOOST_ATOMIC_API_TEST_HELPERS_HPP
8 #define BOOST_ATOMIC_API_TEST_HELPERS_HPP
9
10 #include <boost/atomic.hpp>
11 #include <cstring>
12 #include <boost/config.hpp>
13 #include <boost/cstdint.hpp>
14 #include <boost/core/lightweight_test.hpp>
15 #include <boost/type_traits/integral_constant.hpp>
16 #include <boost/type_traits/is_unsigned.hpp>
17
18 /* provide helpers that exercise whether the API
19 functions of "boost::atomic" provide the correct
20 operational semantic in the case of sequential
21 execution */
22
23 static void
24 test_flag_api(void)
25 {
26 #ifndef BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT
27 boost::atomic_flag f = BOOST_ATOMIC_FLAG_INIT;
28 #else
29 boost::atomic_flag f;
30 #endif
31
32 BOOST_TEST( !f.test_and_set() );
33 BOOST_TEST( f.test_and_set() );
34 f.clear();
35 BOOST_TEST( !f.test_and_set() );
36 }
37
38 template<typename T>
39 void test_base_operators(T value1, T value2, T value3)
40 {
41 /* explicit load/store */
42 {
43 boost::atomic<T> a(value1);
44 BOOST_TEST( a.load() == value1 );
45 }
46
47 {
48 boost::atomic<T> a(value1);
49 a.store(value2);
50 BOOST_TEST( a.load() == value2 );
51 }
52
53 /* overloaded assignment/conversion */
54 {
55 boost::atomic<T> a(value1);
56 BOOST_TEST( value1 == a );
57 }
58
59 {
60 boost::atomic<T> a;
61 a = value2;
62 BOOST_TEST( value2 == a );
63 }
64
65 /* exchange-type operators */
66 {
67 boost::atomic<T> a(value1);
68 T n = a.exchange(value2);
69 BOOST_TEST( a.load() == value2 && n == value1 );
70 }
71
72 {
73 boost::atomic<T> a(value1);
74 T expected = value1;
75 bool success = a.compare_exchange_strong(expected, value3);
76 BOOST_TEST( success );
77 BOOST_TEST( a.load() == value3 && expected == value1 );
78 }
79
80 {
81 boost::atomic<T> a(value1);
82 T expected = value2;
83 bool success = a.compare_exchange_strong(expected, value3);
84 BOOST_TEST( !success );
85 BOOST_TEST( a.load() == value1 && expected == value1 );
86 }
87
88 {
89 boost::atomic<T> a(value1);
90 T expected;
91 bool success;
92 do {
93 expected = value1;
94 success = a.compare_exchange_weak(expected, value3);
95 } while(!success);
96 BOOST_TEST( success );
97 BOOST_TEST( a.load() == value3 && expected == value1 );
98 }
99
100 {
101 boost::atomic<T> a(value1);
102 T expected;
103 bool success;
104 do {
105 expected = value2;
106 success = a.compare_exchange_weak(expected, value3);
107 if (expected != value2)
108 break;
109 } while(!success);
110 BOOST_TEST( !success );
111 BOOST_TEST( a.load() == value1 && expected == value1 );
112 }
113 }
114
115 // T requires an int constructor
116 template <typename T>
117 void test_constexpr_ctor()
118 {
119 #ifndef BOOST_NO_CXX11_CONSTEXPR
120 const T value(0);
121 const boost::atomic<T> tester(value);
122 BOOST_TEST( tester == value );
123 #endif
124 }
125
126 template<typename T, typename D, typename AddType>
127 void test_additive_operators_with_type(T value, D delta)
128 {
129 /* note: the tests explicitly cast the result of any addition
130 to the type to be tested to force truncation of the result to
131 the correct range in case of overflow */
132
133 /* explicit add/sub */
134 {
135 boost::atomic<T> a(value);
136 T n = a.fetch_add(delta);
137 BOOST_TEST( a.load() == T((AddType)value + delta) );
138 BOOST_TEST( n == value );
139 }
140
141 {
142 boost::atomic<T> a(value);
143 T n = a.fetch_sub(delta);
144 BOOST_TEST( a.load() == T((AddType)value - delta) );
145 BOOST_TEST( n == value );
146 }
147
148 /* overloaded modify/assign*/
149 {
150 boost::atomic<T> a(value);
151 T n = (a += delta);
152 BOOST_TEST( a.load() == T((AddType)value + delta) );
153 BOOST_TEST( n == T((AddType)value + delta) );
154 }
155
156 {
157 boost::atomic<T> a(value);
158 T n = (a -= delta);
159 BOOST_TEST( a.load() == T((AddType)value - delta) );
160 BOOST_TEST( n == T((AddType)value - delta) );
161 }
162
163 /* overloaded increment/decrement */
164 {
165 boost::atomic<T> a(value);
166 T n = a++;
167 BOOST_TEST( a.load() == T((AddType)value + 1) );
168 BOOST_TEST( n == value );
169 }
170
171 {
172 boost::atomic<T> a(value);
173 T n = ++a;
174 BOOST_TEST( a.load() == T((AddType)value + 1) );
175 BOOST_TEST( n == T((AddType)value + 1) );
176 }
177
178 {
179 boost::atomic<T> a(value);
180 T n = a--;
181 BOOST_TEST( a.load() == T((AddType)value - 1) );
182 BOOST_TEST( n == value );
183 }
184
185 {
186 boost::atomic<T> a(value);
187 T n = --a;
188 BOOST_TEST( a.load() == T((AddType)value - 1) );
189 BOOST_TEST( n == T((AddType)value - 1) );
190 }
191 }
192
193 template<typename T, typename D>
194 void test_additive_operators(T value, D delta)
195 {
196 test_additive_operators_with_type<T, D, T>(value, delta);
197 }
198
199 template<typename T>
200 void test_additive_wrap(T value)
201 {
202 {
203 boost::atomic<T> a(value);
204 T n = a.fetch_add(1) + 1;
205 BOOST_TEST( a.compare_exchange_strong(n, n) );
206 }
207 {
208 boost::atomic<T> a(value);
209 T n = a.fetch_sub(1) - 1;
210 BOOST_TEST( a.compare_exchange_strong(n, n) );
211 }
212 }
213
214 template<typename T>
215 void test_bit_operators(T value, T delta)
216 {
217 /* explicit and/or/xor */
218 {
219 boost::atomic<T> a(value);
220 T n = a.fetch_and(delta);
221 BOOST_TEST( a.load() == T(value & delta) );
222 BOOST_TEST( n == value );
223 }
224
225 {
226 boost::atomic<T> a(value);
227 T n = a.fetch_or(delta);
228 BOOST_TEST( a.load() == T(value | delta) );
229 BOOST_TEST( n == value );
230 }
231
232 {
233 boost::atomic<T> a(value);
234 T n = a.fetch_xor(delta);
235 BOOST_TEST( a.load() == T(value ^ delta) );
236 BOOST_TEST( n == value );
237 }
238
239 /* overloaded modify/assign */
240 {
241 boost::atomic<T> a(value);
242 T n = (a &= delta);
243 BOOST_TEST( a.load() == T(value & delta) );
244 BOOST_TEST( n == T(value & delta) );
245 }
246
247 {
248 boost::atomic<T> a(value);
249 T n = (a |= delta);
250 BOOST_TEST( a.load() == T(value | delta) );
251 BOOST_TEST( n == T(value | delta) );
252 }
253
254 {
255 boost::atomic<T> a(value);
256 T n = (a ^= delta);
257 BOOST_TEST( a.load() == T(value ^ delta) );
258 BOOST_TEST( n == T(value ^ delta) );
259 }
260 }
261
262 template<typename T>
263 void do_test_integral_api(boost::false_type)
264 {
265 BOOST_TEST( sizeof(boost::atomic<T>) >= sizeof(T));
266
267 test_base_operators<T>(42, 43, 44);
268 test_additive_operators<T, T>(42, 17);
269 test_bit_operators<T>((T)0x5f5f5f5f5f5f5f5fULL, (T)0xf5f5f5f5f5f5f5f5ULL);
270
271 /* test for unsigned overflow/underflow */
272 test_additive_operators<T, T>((T)-1, 1);
273 test_additive_operators<T, T>(0, 1);
274 /* test for signed overflow/underflow */
275 test_additive_operators<T, T>(((T)-1) >> (sizeof(T) * 8 - 1), 1);
276 test_additive_operators<T, T>(1 + (((T)-1) >> (sizeof(T) * 8 - 1)), 1);
277 }
278
279 template<typename T>
280 void do_test_integral_api(boost::true_type)
281 {
282 do_test_integral_api<T>(boost::false_type());
283
284 test_additive_wrap<T>(0u);
285 test_additive_wrap<T>(~(T)0u);
286 test_additive_wrap<T>((~(T)0u) << (sizeof(T) * 8 - 1));
287 test_additive_wrap<T>(~((~(T)0u) << (sizeof(T) * 8 - 1)));
288 }
289
290 template<typename T>
291 inline void test_integral_api(void)
292 {
293 do_test_integral_api<T>(boost::is_unsigned<T>());
294 }
295
296 template<typename T>
297 void test_pointer_api(void)
298 {
299 BOOST_TEST( sizeof(boost::atomic<T *>) >= sizeof(T *));
300 BOOST_TEST( sizeof(boost::atomic<void *>) >= sizeof(T *));
301
302 T values[3];
303
304 test_base_operators<T*>(&values[0], &values[1], &values[2]);
305 test_additive_operators<T*>(&values[1], 1);
306
307 test_base_operators<void*>(&values[0], &values[1], &values[2]);
308 test_additive_operators_with_type<void*, int, char*>(&values[1], 1);
309
310 #if defined(BOOST_HAS_INTPTR_T)
311 boost::atomic<void *> ptr;
312 boost::atomic<boost::intptr_t> integral;
313 BOOST_TEST( ptr.is_lock_free() == integral.is_lock_free() );
314 #endif
315 }
316
317 enum test_enum {
318 foo, bar, baz
319 };
320
321 static void
322 test_enum_api(void)
323 {
324 test_base_operators(foo, bar, baz);
325 }
326
327 template<typename T>
328 struct test_struct {
329 typedef T value_type;
330 value_type i;
331 inline bool operator==(const test_struct & c) const {return i == c.i;}
332 inline bool operator!=(const test_struct & c) const {return i != c.i;}
333 };
334
335 template<typename T>
336 void
337 test_struct_api(void)
338 {
339 T a = {1}, b = {2}, c = {3};
340
341 test_base_operators(a, b, c);
342
343 {
344 boost::atomic<T> sa;
345 boost::atomic<typename T::value_type> si;
346 BOOST_TEST( sa.is_lock_free() == si.is_lock_free() );
347 }
348 }
349
350 template<typename T>
351 struct test_struct_x2 {
352 typedef T value_type;
353 value_type i, j;
354 inline bool operator==(const test_struct_x2 & c) const {return i == c.i && j == c.j;}
355 inline bool operator!=(const test_struct_x2 & c) const {return i != c.i && j != c.j;}
356 };
357
358 template<typename T>
359 void
360 test_struct_x2_api(void)
361 {
362 T a = {1, 1}, b = {2, 2}, c = {3, 3};
363
364 test_base_operators(a, b, c);
365 }
366
367 struct large_struct {
368 long data[64];
369
370 inline bool operator==(const large_struct & c) const
371 {
372 return std::memcmp(data, &c.data, sizeof(data)) == 0;
373 }
374 inline bool operator!=(const large_struct & c) const
375 {
376 return std::memcmp(data, &c.data, sizeof(data)) != 0;
377 }
378 };
379
380 static void
381 test_large_struct_api(void)
382 {
383 large_struct a = {{1}}, b = {{2}}, c = {{3}};
384 test_base_operators(a, b, c);
385 }
386
387 struct test_struct_with_ctor {
388 typedef unsigned int value_type;
389 value_type i;
390 test_struct_with_ctor() : i(0x01234567) {}
391 inline bool operator==(const test_struct_with_ctor & c) const {return i == c.i;}
392 inline bool operator!=(const test_struct_with_ctor & c) const {return i != c.i;}
393 };
394
395 static void
396 test_struct_with_ctor_api(void)
397 {
398 {
399 test_struct_with_ctor s;
400 boost::atomic<test_struct_with_ctor> sa;
401 // Check that the default constructor was called
402 BOOST_TEST( sa.load() == s );
403 }
404
405 test_struct_with_ctor a, b, c;
406 a.i = 1;
407 b.i = 2;
408 c.i = 3;
409
410 test_base_operators(a, b, c);
411 }
412
413 #endif