]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/atomic/test/api_test_helpers.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / atomic / test / api_test_helpers.hpp
1 // Copyright (c) 2011 Helge Bahmann
2 // Copyright (c) 2017 Andrey Semashev
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7
8 #ifndef BOOST_ATOMIC_API_TEST_HELPERS_HPP
9 #define BOOST_ATOMIC_API_TEST_HELPERS_HPP
10
11 #include <boost/atomic.hpp>
12 #include <cstddef>
13 #include <cstring>
14 #include <limits>
15 #include <iostream>
16 #include <boost/config.hpp>
17 #include <boost/cstdint.hpp>
18 #include <boost/type_traits/integral_constant.hpp>
19 #include <boost/type_traits/is_signed.hpp>
20 #include <boost/type_traits/is_unsigned.hpp>
21
22 struct test_stream_type
23 {
24 typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
25 typedef std::basic_ios< char, std::char_traits< char > >& (*basic_ios_manip)(std::basic_ios< char, std::char_traits< char > >&);
26 typedef std::ostream& (*stream_manip)(std::ostream&);
27
28 template< typename T >
29 test_stream_type const& operator<< (T const& value) const
30 {
31 std::cerr << value;
32 return *this;
33 }
34
35 test_stream_type const& operator<< (ios_base_manip manip) const
36 {
37 std::cerr << manip;
38 return *this;
39 }
40 test_stream_type const& operator<< (basic_ios_manip manip) const
41 {
42 std::cerr << manip;
43 return *this;
44 }
45 test_stream_type const& operator<< (stream_manip manip) const
46 {
47 std::cerr << manip;
48 return *this;
49 }
50
51 // Make sure characters are printed as numbers if tests fail
52 test_stream_type const& operator<< (char value) const
53 {
54 std::cerr << static_cast< int >(value);
55 return *this;
56 }
57 test_stream_type const& operator<< (signed char value) const
58 {
59 std::cerr << static_cast< int >(value);
60 return *this;
61 }
62 test_stream_type const& operator<< (unsigned char value) const
63 {
64 std::cerr << static_cast< unsigned int >(value);
65 return *this;
66 }
67 test_stream_type const& operator<< (short value) const
68 {
69 std::cerr << static_cast< int >(value);
70 return *this;
71 }
72 test_stream_type const& operator<< (unsigned short value) const
73 {
74 std::cerr << static_cast< unsigned int >(value);
75 return *this;
76 }
77
78 #if defined(BOOST_HAS_INT128)
79 // Some GCC versions don't provide output operators for __int128
80 test_stream_type const& operator<< (boost::int128_type const& v) const
81 {
82 std::cerr << static_cast< long long >(v);
83 return *this;
84 }
85 test_stream_type const& operator<< (boost::uint128_type const& v) const
86 {
87 std::cerr << static_cast< unsigned long long >(v);
88 return *this;
89 }
90 #endif // defined(BOOST_HAS_INT128)
91 };
92
93 const test_stream_type test_stream = {};
94
95 #define BOOST_LIGHTWEIGHT_TEST_OSTREAM test_stream
96
97 #include <boost/core/lightweight_test.hpp>
98
99 /* provide helpers that exercise whether the API
100 functions of "boost::atomic" provide the correct
101 operational semantic in the case of sequential
102 execution */
103
104 static void
105 test_flag_api(void)
106 {
107 #ifndef BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT
108 boost::atomic_flag f = BOOST_ATOMIC_FLAG_INIT;
109 #else
110 boost::atomic_flag f;
111 #endif
112
113 BOOST_TEST( !f.test_and_set() );
114 BOOST_TEST( f.test_and_set() );
115 f.clear();
116 BOOST_TEST( !f.test_and_set() );
117 }
118
119 template<typename T>
120 void test_base_operators(T value1, T value2, T value3)
121 {
122 /* explicit load/store */
123 {
124 boost::atomic<T> a(value1);
125 BOOST_TEST_EQ( a.load(), value1 );
126 }
127
128 {
129 boost::atomic<T> a(value1);
130 a.store(value2);
131 BOOST_TEST_EQ( a.load(), value2 );
132 }
133
134 /* overloaded assignment/conversion */
135 {
136 boost::atomic<T> a(value1);
137 BOOST_TEST( value1 == a );
138 }
139
140 {
141 boost::atomic<T> a;
142 a = value2;
143 BOOST_TEST( value2 == a );
144 }
145
146 /* exchange-type operators */
147 {
148 boost::atomic<T> a(value1);
149 T n = a.exchange(value2);
150 BOOST_TEST_EQ( a.load(), value2 );
151 BOOST_TEST_EQ( n, value1 );
152 }
153
154 {
155 boost::atomic<T> a(value1);
156 T expected = value1;
157 bool success = a.compare_exchange_strong(expected, value3);
158 BOOST_TEST( success );
159 BOOST_TEST_EQ( a.load(), value3 );
160 BOOST_TEST_EQ( expected, value1 );
161 }
162
163 {
164 boost::atomic<T> a(value1);
165 T expected = value2;
166 bool success = a.compare_exchange_strong(expected, value3);
167 BOOST_TEST( !success );
168 BOOST_TEST_EQ( a.load(), value1 );
169 BOOST_TEST_EQ( expected, value1 );
170 }
171
172 {
173 boost::atomic<T> a(value1);
174 T expected;
175 bool success;
176 do {
177 expected = value1;
178 success = a.compare_exchange_weak(expected, value3);
179 } while(!success);
180 BOOST_TEST( success );
181 BOOST_TEST_EQ( a.load(), value3 );
182 BOOST_TEST_EQ( expected, value1 );
183 }
184
185 {
186 boost::atomic<T> a(value1);
187 T expected;
188 bool success;
189 do {
190 expected = value2;
191 success = a.compare_exchange_weak(expected, value3);
192 if (expected != value2)
193 break;
194 } while(!success);
195 BOOST_TEST( !success );
196 BOOST_TEST_EQ( a.load(), value1 );
197 BOOST_TEST_EQ( expected, value1 );
198 }
199 }
200
201 // T requires an int constructor
202 template <typename T>
203 void test_constexpr_ctor()
204 {
205 #ifndef BOOST_NO_CXX11_CONSTEXPR
206 const T value(0);
207 const boost::atomic<T> tester(value);
208 BOOST_TEST( tester == value );
209 #endif
210 }
211
212 //! The type traits provides max and min values of type D that can be added/subtracted to T(0) without signed overflow
213 template< typename T, typename D, bool IsSigned = boost::is_signed< D >::value >
214 struct distance_limits
215 {
216 static D min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
217 {
218 return (std::numeric_limits< D >::min)();
219 }
220 static D max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
221 {
222 return (std::numeric_limits< D >::max)();
223 }
224 };
225
226 #if defined(BOOST_MSVC)
227 #pragma warning(push)
228 // 'static_cast': truncation of constant value. There is no actual truncation happening because
229 // the cast is only performed if the value fits in the range of the result.
230 #pragma warning(disable: 4309)
231 #endif
232
233 template< typename T, typename D >
234 struct distance_limits< T*, D, true >
235 {
236 static D min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
237 {
238 const std::ptrdiff_t ptrdiff = (std::numeric_limits< std::ptrdiff_t >::min)() / static_cast< std::ptrdiff_t >(sizeof(T));
239 const D diff = (std::numeric_limits< D >::min)();
240 // Both values are negative. Return the closest value to zero.
241 return diff < ptrdiff ? static_cast< D >(ptrdiff) : diff;
242 }
243 static D max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
244 {
245 const std::ptrdiff_t ptrdiff = (std::numeric_limits< std::ptrdiff_t >::max)() / static_cast< std::ptrdiff_t >(sizeof(T));
246 const D diff = (std::numeric_limits< D >::max)();
247 // Both values are positive. Return the closest value to zero.
248 return diff > ptrdiff ? static_cast< D >(ptrdiff) : diff;
249 }
250 };
251
252 template< typename T, typename D >
253 struct distance_limits< T*, D, false >
254 {
255 static D min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
256 {
257 return (std::numeric_limits< D >::min)();
258 }
259 static D max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
260 {
261 const std::size_t ptrdiff = static_cast< std::size_t >((std::numeric_limits< std::ptrdiff_t >::max)()) / sizeof(T);
262 const D diff = (std::numeric_limits< D >::max)();
263 return diff > ptrdiff ? static_cast< D >(ptrdiff) : diff;
264 }
265 };
266
267 #if defined(BOOST_HAS_INT128)
268
269 // At least libstdc++ does not specialize std::numeric_limits for __int128 in strict mode (i.e. with GNU extensions disabled).
270 // So we have to specialize the limits ourself. We assume two's complement signed representation.
271 template< typename T, bool IsSigned >
272 struct distance_limits< T, boost::int128_type, IsSigned >
273 {
274 static boost::int128_type min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
275 {
276 return -(max)() - 1;
277 }
278 static boost::int128_type max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
279 {
280 return static_cast< boost::int128_type >((~static_cast< boost::uint128_type >(0u)) >> 1);
281 }
282 };
283
284 template< typename T, bool IsSigned >
285 struct distance_limits< T, boost::uint128_type, IsSigned >
286 {
287 static boost::uint128_type min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
288 {
289 return 0u;
290 }
291 static boost::uint128_type max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
292 {
293 return ~static_cast< boost::uint128_type >(0u);
294 }
295 };
296
297 #endif // defined(BOOST_HAS_INT128)
298
299 #if defined(BOOST_MSVC)
300 #pragma warning(pop)
301 #endif
302
303 template<typename T, typename D, typename AddType>
304 void test_additive_operators_with_type_and_test()
305 {
306 // Note: This set of tests is extracted to a separate function because otherwise MSVC-10 for x64 generates broken code
307 const T zero_value = 0;
308 const D zero_diff = 0;
309 const D one_diff = 1;
310 const AddType zero_add = 0;
311 {
312 boost::atomic<T> a(zero_value);
313 bool f = a.add_and_test(zero_diff);
314 BOOST_TEST_EQ( f, true );
315 BOOST_TEST_EQ( a.load(), zero_value );
316
317 f = a.add_and_test(one_diff);
318 BOOST_TEST_EQ( f, false );
319 BOOST_TEST_EQ( a.load(), T(zero_add + one_diff) );
320 }
321 {
322 boost::atomic<T> a(zero_value);
323 bool f = a.add_and_test((distance_limits< T, D >::max)());
324 BOOST_TEST_EQ( f, false );
325 BOOST_TEST_EQ( a.load(), T(zero_add + (distance_limits< T, D >::max)()) );
326 }
327 {
328 boost::atomic<T> a(zero_value);
329 bool f = a.add_and_test((distance_limits< T, D >::min)());
330 BOOST_TEST_EQ( f, ((distance_limits< T, D >::min)() == 0) );
331 BOOST_TEST_EQ( a.load(), T(zero_add + (distance_limits< T, D >::min)()) );
332 }
333
334 {
335 boost::atomic<T> a(zero_value);
336 bool f = a.sub_and_test(zero_diff);
337 BOOST_TEST_EQ( f, true );
338 BOOST_TEST_EQ( a.load(), zero_value );
339
340 f = a.sub_and_test(one_diff);
341 BOOST_TEST_EQ( f, false );
342 BOOST_TEST_EQ( a.load(), T(zero_add - one_diff) );
343 }
344 {
345 boost::atomic<T> a(zero_value);
346 bool f = a.sub_and_test((distance_limits< T, D >::max)());
347 BOOST_TEST_EQ( f, false );
348 BOOST_TEST_EQ( a.load(), T(zero_add - (distance_limits< T, D >::max)()) );
349 }
350 {
351 boost::atomic<T> a(zero_value);
352 bool f = a.sub_and_test((distance_limits< T, D >::min)());
353 BOOST_TEST_EQ( f, ((distance_limits< T, D >::min)() == 0) );
354 BOOST_TEST_EQ( a.load(), T(zero_add - (distance_limits< T, D >::min)()) );
355 }
356 }
357
358 template<typename T, typename D, typename AddType>
359 void test_additive_operators_with_type(T value, D delta)
360 {
361 /* note: the tests explicitly cast the result of any addition
362 to the type to be tested to force truncation of the result to
363 the correct range in case of overflow */
364
365 /* explicit add/sub */
366 {
367 boost::atomic<T> a(value);
368 T n = a.fetch_add(delta);
369 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
370 BOOST_TEST_EQ( n, value );
371 }
372
373 {
374 boost::atomic<T> a(value);
375 T n = a.fetch_sub(delta);
376 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
377 BOOST_TEST_EQ( n, value );
378 }
379
380 /* overloaded modify/assign*/
381 {
382 boost::atomic<T> a(value);
383 T n = (a += delta);
384 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
385 BOOST_TEST_EQ( n, T((AddType)value + delta) );
386 }
387
388 {
389 boost::atomic<T> a(value);
390 T n = (a -= delta);
391 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
392 BOOST_TEST_EQ( n, T((AddType)value - delta) );
393 }
394
395 /* overloaded increment/decrement */
396 {
397 boost::atomic<T> a(value);
398 T n = a++;
399 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
400 BOOST_TEST_EQ( n, value );
401 }
402
403 {
404 boost::atomic<T> a(value);
405 T n = ++a;
406 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
407 BOOST_TEST_EQ( n, T((AddType)value + 1) );
408 }
409
410 {
411 boost::atomic<T> a(value);
412 T n = a--;
413 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
414 BOOST_TEST_EQ( n, value );
415 }
416
417 {
418 boost::atomic<T> a(value);
419 T n = --a;
420 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
421 BOOST_TEST_EQ( n, T((AddType)value - 1) );
422 }
423
424 // Opaque operations
425 {
426 boost::atomic<T> a(value);
427 a.opaque_add(delta);
428 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
429 }
430
431 {
432 boost::atomic<T> a(value);
433 a.opaque_sub(delta);
434 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
435 }
436
437 // Modify and test operations
438 test_additive_operators_with_type_and_test< T, D, AddType >();
439 }
440
441 template<typename T, typename D>
442 void test_additive_operators(T value, D delta)
443 {
444 test_additive_operators_with_type<T, D, T>(value, delta);
445 }
446
447 template< typename T >
448 void test_negation()
449 {
450 {
451 boost::atomic<T> a((T)1);
452 T n = a.fetch_negate();
453 BOOST_TEST_EQ( a.load(), (T)-1 );
454 BOOST_TEST_EQ( n, (T)1 );
455
456 n = a.fetch_negate();
457 BOOST_TEST_EQ( a.load(), (T)1 );
458 BOOST_TEST_EQ( n, (T)-1 );
459 }
460 {
461 boost::atomic<T> a((T)1);
462 a.opaque_negate();
463 BOOST_TEST_EQ( a.load(), (T)-1 );
464
465 a.opaque_negate();
466 BOOST_TEST_EQ( a.load(), (T)1 );
467 }
468 }
469
470 template<typename T>
471 void test_additive_wrap(T value)
472 {
473 {
474 boost::atomic<T> a(value);
475 T n = a.fetch_add(1) + (T)1;
476 BOOST_TEST_EQ( a.load(), n );
477 }
478 {
479 boost::atomic<T> a(value);
480 T n = a.fetch_sub(1) - (T)1;
481 BOOST_TEST_EQ( a.load(), n );
482 }
483 }
484
485 template<typename T>
486 void test_bit_operators(T value, T delta)
487 {
488 /* explicit and/or/xor */
489 {
490 boost::atomic<T> a(value);
491 T n = a.fetch_and(delta);
492 BOOST_TEST_EQ( a.load(), T(value & delta) );
493 BOOST_TEST_EQ( n, value );
494 }
495
496 {
497 boost::atomic<T> a(value);
498 T n = a.fetch_or(delta);
499 BOOST_TEST_EQ( a.load(), T(value | delta) );
500 BOOST_TEST_EQ( n, value );
501 }
502
503 {
504 boost::atomic<T> a(value);
505 T n = a.fetch_xor(delta);
506 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
507 BOOST_TEST_EQ( n, value );
508 }
509
510 {
511 boost::atomic<T> a(value);
512 T n = a.fetch_complement();
513 BOOST_TEST_EQ( a.load(), T(~value) );
514 BOOST_TEST_EQ( n, value );
515 }
516
517 /* overloaded modify/assign */
518 {
519 boost::atomic<T> a(value);
520 T n = (a &= delta);
521 BOOST_TEST_EQ( a.load(), T(value & delta) );
522 BOOST_TEST_EQ( n, T(value & delta) );
523 }
524
525 {
526 boost::atomic<T> a(value);
527 T n = (a |= delta);
528 BOOST_TEST_EQ( a.load(), T(value | delta) );
529 BOOST_TEST_EQ( n, T(value | delta) );
530 }
531
532 {
533 boost::atomic<T> a(value);
534 T n = (a ^= delta);
535 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
536 BOOST_TEST_EQ( n, T(value ^ delta) );
537 }
538
539 // Opaque operations
540 {
541 boost::atomic<T> a(value);
542 a.opaque_and(delta);
543 BOOST_TEST_EQ( a.load(), T(value & delta) );
544 }
545
546 {
547 boost::atomic<T> a(value);
548 a.opaque_or(delta);
549 BOOST_TEST_EQ( a.load(), T(value | delta) );
550 }
551
552 {
553 boost::atomic<T> a(value);
554 a.opaque_xor(delta);
555 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
556 }
557
558 {
559 boost::atomic<T> a(value);
560 a.opaque_complement();
561 BOOST_TEST_EQ( a.load(), T(~value) );
562 }
563
564 // Modify and test operations
565 {
566 boost::atomic<T> a((T)1);
567 bool f = a.and_and_test((T)1);
568 BOOST_TEST_EQ( f, false );
569 BOOST_TEST_EQ( a.load(), T(1) );
570
571 f = a.and_and_test((T)0);
572 BOOST_TEST_EQ( f, true );
573 BOOST_TEST_EQ( a.load(), T(0) );
574
575 f = a.and_and_test((T)0);
576 BOOST_TEST_EQ( f, true );
577 BOOST_TEST_EQ( a.load(), T(0) );
578 }
579
580 {
581 boost::atomic<T> a((T)0);
582 bool f = a.or_and_test((T)0);
583 BOOST_TEST_EQ( f, true );
584 BOOST_TEST_EQ( a.load(), T(0) );
585
586 f = a.or_and_test((T)1);
587 BOOST_TEST_EQ( f, false );
588 BOOST_TEST_EQ( a.load(), T(1) );
589
590 f = a.or_and_test((T)1);
591 BOOST_TEST_EQ( f, false );
592 BOOST_TEST_EQ( a.load(), T(1) );
593 }
594
595 {
596 boost::atomic<T> a((T)0);
597 bool f = a.xor_and_test((T)0);
598 BOOST_TEST_EQ( f, true );
599 BOOST_TEST_EQ( a.load(), T(0) );
600
601 f = a.xor_and_test((T)1);
602 BOOST_TEST_EQ( f, false );
603 BOOST_TEST_EQ( a.load(), T(1) );
604
605 f = a.xor_and_test((T)1);
606 BOOST_TEST_EQ( f, true );
607 BOOST_TEST_EQ( a.load(), T(0) );
608 }
609
610 // Bit test and modify operations
611 {
612 boost::atomic<T> a((T)42);
613 bool f = a.bit_test_and_set(0);
614 BOOST_TEST_EQ( f, false );
615 BOOST_TEST_EQ( a.load(), T(43) );
616
617 f = a.bit_test_and_set(1);
618 BOOST_TEST_EQ( f, true );
619 BOOST_TEST_EQ( a.load(), T(43) );
620
621 f = a.bit_test_and_set(2);
622 BOOST_TEST_EQ( f, false );
623 BOOST_TEST_EQ( a.load(), T(47) );
624 }
625
626 {
627 boost::atomic<T> a((T)42);
628 bool f = a.bit_test_and_reset(0);
629 BOOST_TEST_EQ( f, false );
630 BOOST_TEST_EQ( a.load(), T(42) );
631
632 f = a.bit_test_and_reset(1);
633 BOOST_TEST_EQ( f, true );
634 BOOST_TEST_EQ( a.load(), T(40) );
635
636 f = a.bit_test_and_set(2);
637 BOOST_TEST_EQ( f, false );
638 BOOST_TEST_EQ( a.load(), T(44) );
639 }
640
641 {
642 boost::atomic<T> a((T)42);
643 bool f = a.bit_test_and_complement(0);
644 BOOST_TEST_EQ( f, false );
645 BOOST_TEST_EQ( a.load(), T(43) );
646
647 f = a.bit_test_and_complement(1);
648 BOOST_TEST_EQ( f, true );
649 BOOST_TEST_EQ( a.load(), T(41) );
650
651 f = a.bit_test_and_complement(2);
652 BOOST_TEST_EQ( f, false );
653 BOOST_TEST_EQ( a.load(), T(45) );
654 }
655 }
656
657 template<typename T>
658 void do_test_integral_api(boost::false_type)
659 {
660 BOOST_TEST( sizeof(boost::atomic<T>) >= sizeof(T));
661
662 test_base_operators<T>(42, 43, 44);
663 test_additive_operators<T, T>(42, 17);
664 test_bit_operators<T>((T)0x5f5f5f5f5f5f5f5fULL, (T)0xf5f5f5f5f5f5f5f5ULL);
665
666 /* test for unsigned overflow/underflow */
667 test_additive_operators<T, T>((T)-1, 1);
668 test_additive_operators<T, T>(0, 1);
669 /* test for signed overflow/underflow */
670 test_additive_operators<T, T>(((T)-1) >> (sizeof(T) * 8 - 1), 1);
671 test_additive_operators<T, T>(1 + (((T)-1) >> (sizeof(T) * 8 - 1)), 1);
672 }
673
674 template<typename T>
675 void do_test_integral_api(boost::true_type)
676 {
677 do_test_integral_api<T>(boost::false_type());
678
679 test_additive_wrap<T>(0u);
680 BOOST_CONSTEXPR_OR_CONST T all_ones = ~(T)0u;
681 test_additive_wrap<T>(all_ones);
682 BOOST_CONSTEXPR_OR_CONST T max_signed_twos_compl = all_ones >> 1;
683 test_additive_wrap<T>(all_ones ^ max_signed_twos_compl);
684 test_additive_wrap<T>(max_signed_twos_compl);
685 }
686
687 template<typename T>
688 inline void test_integral_api(void)
689 {
690 do_test_integral_api<T>(boost::is_unsigned<T>());
691
692 if (boost::is_signed<T>::value)
693 test_negation<T>();
694 }
695
696 template<typename T>
697 void test_pointer_api(void)
698 {
699 BOOST_TEST_GE( sizeof(boost::atomic<T *>), sizeof(T *));
700 BOOST_TEST_GE( sizeof(boost::atomic<void *>), sizeof(T *));
701
702 T values[3];
703
704 test_base_operators<T*>(&values[0], &values[1], &values[2]);
705 test_additive_operators<T*>(&values[1], 1);
706
707 test_base_operators<void*>(&values[0], &values[1], &values[2]);
708
709 #if defined(BOOST_HAS_INTPTR_T)
710 boost::atomic<void *> ptr;
711 boost::atomic<boost::intptr_t> integral;
712 BOOST_TEST_EQ( ptr.is_lock_free(), integral.is_lock_free() );
713 #endif
714 }
715
716 enum test_enum
717 {
718 foo, bar, baz
719 };
720
721 static void
722 test_enum_api(void)
723 {
724 test_base_operators(foo, bar, baz);
725 }
726
727 template<typename T>
728 struct test_struct
729 {
730 typedef T value_type;
731 value_type i;
732 inline bool operator==(const test_struct & c) const {return i == c.i;}
733 inline bool operator!=(const test_struct & c) const {return i != c.i;}
734 };
735
736 template< typename Char, typename Traits, typename T >
737 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct< T > const& s)
738 {
739 test_stream << "{" << s.i << "}";
740 return strm;
741 }
742
743 template<typename T>
744 void
745 test_struct_api(void)
746 {
747 T a = {1}, b = {2}, c = {3};
748
749 test_base_operators(a, b, c);
750
751 {
752 boost::atomic<T> sa;
753 boost::atomic<typename T::value_type> si;
754 BOOST_TEST_EQ( sa.is_lock_free(), si.is_lock_free() );
755 }
756 }
757
758 template<typename T>
759 struct test_struct_x2
760 {
761 typedef T value_type;
762 value_type i, j;
763 inline bool operator==(const test_struct_x2 & c) const {return i == c.i && j == c.j;}
764 inline bool operator!=(const test_struct_x2 & c) const {return i != c.i && j != c.j;}
765 };
766
767 template< typename Char, typename Traits, typename T >
768 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct_x2< T > const& s)
769 {
770 test_stream << "{" << s.i << ", " << s.j << "}";
771 return strm;
772 }
773
774 template<typename T>
775 void
776 test_struct_x2_api(void)
777 {
778 T a = {1, 1}, b = {2, 2}, c = {3, 3};
779
780 test_base_operators(a, b, c);
781 }
782
783 struct large_struct
784 {
785 long data[64];
786
787 inline bool operator==(const large_struct & c) const
788 {
789 return std::memcmp(data, &c.data, sizeof(data)) == 0;
790 }
791 inline bool operator!=(const large_struct & c) const
792 {
793 return std::memcmp(data, &c.data, sizeof(data)) != 0;
794 }
795 };
796
797 template< typename Char, typename Traits >
798 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, large_struct const&)
799 {
800 strm << "[large_struct]";
801 return strm;
802 }
803
804 static void
805 test_large_struct_api(void)
806 {
807 large_struct a = {{1}}, b = {{2}}, c = {{3}};
808 test_base_operators(a, b, c);
809 }
810
811 struct test_struct_with_ctor
812 {
813 typedef unsigned int value_type;
814 value_type i;
815 test_struct_with_ctor() : i(0x01234567) {}
816 inline bool operator==(const test_struct_with_ctor & c) const {return i == c.i;}
817 inline bool operator!=(const test_struct_with_ctor & c) const {return i != c.i;}
818 };
819
820 template< typename Char, typename Traits >
821 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct_with_ctor const&)
822 {
823 strm << "[test_struct_with_ctor]";
824 return strm;
825 }
826
827 static void
828 test_struct_with_ctor_api(void)
829 {
830 {
831 test_struct_with_ctor s;
832 boost::atomic<test_struct_with_ctor> sa;
833 // Check that the default constructor was called
834 BOOST_TEST( sa.load() == s );
835 }
836
837 test_struct_with_ctor a, b, c;
838 a.i = 1;
839 b.i = 2;
840 c.i = 3;
841
842 test_base_operators(a, b, c);
843 }
844
845 #endif