1 // Copyright (c) 2011 Helge Bahmann
2 // Copyright (c) 2017 - 2021 Andrey Semashev
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)
8 #ifndef BOOST_ATOMIC_API_TEST_HELPERS_HPP
9 #define BOOST_ATOMIC_API_TEST_HELPERS_HPP
11 #include <boost/atomic.hpp>
18 #include <boost/config.hpp>
19 #include <boost/cstdint.hpp>
20 #include <boost/type.hpp>
21 #include <boost/core/enable_if.hpp>
22 #include <boost/type_traits/integral_constant.hpp>
23 #include <boost/type_traits/alignment_of.hpp>
24 #include <boost/type_traits/is_pointer.hpp>
25 #include <boost/type_traits/is_signed.hpp>
26 #include <boost/type_traits/is_unsigned.hpp>
27 #include <boost/type_traits/make_signed.hpp>
28 #include <boost/type_traits/make_unsigned.hpp>
29 #include <boost/type_traits/conditional.hpp>
31 #include "lightweight_test_stream.hpp"
32 #include "value_with_epsilon.hpp"
33 #include "atomic_wrapper.hpp"
35 const unsigned int max_weak_cas_loops = 1000;
37 template< typename T >
39 public boost::false_type
43 template< typename T >
44 struct is_atomic< boost::atomic< T > > :
45 public boost::true_type
49 template< typename T >
50 struct is_atomic< boost::ipc_atomic< T > > :
51 public boost::true_type
55 template< typename T >
56 struct is_atomic_ref :
57 public boost::false_type
61 template< typename T >
62 struct is_atomic_ref< boost::atomic_ref< T > > :
63 public boost::true_type
67 template< typename T >
68 struct is_atomic_ref< boost::ipc_atomic_ref< T > > :
69 public boost::true_type
73 template< typename Flag >
74 inline void test_flag_api(void)
76 #ifndef BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT
77 Flag f = BOOST_ATOMIC_FLAG_INIT;
82 BOOST_TEST( !f.test() );
83 BOOST_TEST( !f.test_and_set() );
84 BOOST_TEST( f.test() );
85 BOOST_TEST( f.test_and_set() );
86 BOOST_TEST( f.test() );
88 BOOST_TEST( !f.test() );
89 BOOST_TEST( !f.test_and_set() );
92 template< typename T >
93 inline typename boost::enable_if< is_atomic< T > >::type test_atomic_type_traits(boost::type< T >)
95 BOOST_TEST_GE(sizeof(T), sizeof(typename T::value_type));
98 template< typename T >
99 inline typename boost::enable_if< is_atomic_ref< T > >::type test_atomic_type_traits(boost::type< T >)
101 if (T::is_always_lock_free)
103 BOOST_TEST_GE(T::required_alignment, boost::alignment_of< typename T::value_type >::value);
107 // Lock-based implementation should not require alignment higher than alignof(T)
108 BOOST_TEST_EQ(T::required_alignment, boost::alignment_of< typename T::value_type >::value);
112 template< template< typename > class Wrapper, typename T >
113 void test_base_operators(T value1, T value2, T value3)
115 test_atomic_type_traits(boost::type< typename Wrapper<T>::atomic_type >());
117 if (is_atomic< typename Wrapper<T>::atomic_type >::value)
119 // default constructor must value-initialize the contained object
121 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
122 BOOST_TEST_EQ( a.load(), T() );
125 // explicit load/store
127 Wrapper<T> wrapper(value1);
128 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
129 BOOST_TEST_EQ( a.load(), value1 );
133 Wrapper<T> wrapper(value1);
134 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
136 BOOST_TEST_EQ( a.load(), value2 );
139 // overloaded assignment/conversion
141 Wrapper<T> wrapper(value1);
142 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
143 BOOST_TEST( value1 == a );
147 Wrapper<T> wrapper(value1);
148 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
150 BOOST_TEST( value2 == a );
153 // exchange-type operators
155 Wrapper<T> wrapper(value1);
156 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
157 T n = a.exchange(value2);
158 BOOST_TEST_EQ( a.load(), value2 );
159 BOOST_TEST_EQ( n, value1 );
163 Wrapper<T> wrapper(value1);
164 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
166 bool success = a.compare_exchange_strong(expected, value3);
167 BOOST_TEST( success );
168 BOOST_TEST_EQ( a.load(), value3 );
169 BOOST_TEST_EQ( expected, value1 );
173 Wrapper<T> wrapper(value1);
174 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
176 bool success = a.compare_exchange_strong(expected, value3);
177 BOOST_TEST( !success );
178 BOOST_TEST_EQ( a.load(), value1 );
179 BOOST_TEST_EQ( expected, value1 );
183 Wrapper<T> wrapper(value1);
184 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
186 unsigned int loops = 0;
187 bool success = false;
191 success = a.compare_exchange_weak(expected, value3);
194 while (!success && loops < max_weak_cas_loops);
195 BOOST_TEST( success );
196 BOOST_TEST_EQ( a.load(), value3 );
197 BOOST_TEST_EQ( expected, value1 );
201 Wrapper<T> wrapper(value1);
202 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
204 unsigned int loops = 0;
205 bool success = false;
209 success = a.compare_exchange_weak(expected, value3);
210 if (expected != value2)
214 while (!success && loops < max_weak_cas_loops);
215 BOOST_TEST( !success );
216 BOOST_TEST_EQ( a.load(), value1 );
217 BOOST_TEST_EQ( expected, value1 );
221 //! Tests whether boost::atomic supports constexpr constructor. Note that boost::atomic_ref (as std::atomic_ref) does not support constexpr constructor.
222 template< typename T >
223 void test_constexpr_ctor()
225 #ifndef BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT
226 static constexpr T value = T();
228 constexpr boost::atomic<T> tester_default;
229 BOOST_TEST_EQ(tester_default.load(boost::memory_order_relaxed), value);
231 constexpr boost::atomic<T> tester_init(value);
232 BOOST_TEST_EQ(tester_init.load(boost::memory_order_relaxed), value);
236 //! The type traits provides max and min values of type D that can be added/subtracted to T(0) without signed overflow
237 template< typename T, typename D, bool IsSigned = boost::is_signed< D >::value >
238 struct distance_limits
240 //! Difference type D promoted to the width of type T
241 typedef typename boost::conditional<
243 boost::make_signed< T >,
244 boost::make_unsigned< T >
245 >::type::type promoted_difference_type;
247 static D min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
249 return (std::numeric_limits< D >::min)();
251 static D max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
253 return (std::numeric_limits< D >::max)();
257 #if defined(BOOST_MSVC)
258 #pragma warning(push)
259 // 'static_cast': truncation of constant value. There is no actual truncation happening because
260 // the cast is only performed if the value fits in the range of the result.
261 #pragma warning(disable: 4309)
264 template< typename T, typename D >
265 struct distance_limits< T*, D, true >
267 //! Difference type D promoted to the width of type T
268 typedef std::ptrdiff_t promoted_difference_type;
270 static D min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
272 const std::ptrdiff_t ptrdiff = (std::numeric_limits< std::ptrdiff_t >::min)() / static_cast< std::ptrdiff_t >(sizeof(T));
273 const D diff = (std::numeric_limits< D >::min)();
274 // Both values are negative. Return the closest value to zero.
275 return diff < ptrdiff ? static_cast< D >(ptrdiff) : diff;
277 static D max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
279 const std::ptrdiff_t ptrdiff = (std::numeric_limits< std::ptrdiff_t >::max)() / static_cast< std::ptrdiff_t >(sizeof(T));
280 const D diff = (std::numeric_limits< D >::max)();
281 // Both values are positive. Return the closest value to zero.
282 return diff > ptrdiff ? static_cast< D >(ptrdiff) : diff;
286 template< typename T, typename D >
287 struct distance_limits< T*, D, false >
289 //! Difference type D promoted to the width of type T
290 typedef std::size_t promoted_difference_type;
292 static D min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
294 return (std::numeric_limits< D >::min)();
296 static D max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
298 const std::size_t ptrdiff = static_cast< std::size_t >((std::numeric_limits< std::ptrdiff_t >::max)()) / sizeof(T);
299 const D diff = (std::numeric_limits< D >::max)();
300 return diff > ptrdiff ? static_cast< D >(ptrdiff) : diff;
304 #if defined(BOOST_HAS_INT128)
306 // At least libstdc++ does not specialize std::numeric_limits for __int128 in strict mode (i.e. with GNU extensions disabled).
307 // So we have to specialize the limits ourself. We assume two's complement signed representation.
308 template< typename T, bool IsSigned >
309 struct distance_limits< T, boost::int128_type, IsSigned >
311 //! Difference type D promoted to the width of type T
312 typedef boost::int128_type promoted_difference_type;
314 static boost::int128_type min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
318 static boost::int128_type max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
320 return static_cast< boost::int128_type >((~static_cast< boost::uint128_type >(0u)) >> 1);
324 template< typename T, bool IsSigned >
325 struct distance_limits< T, boost::uint128_type, IsSigned >
327 //! Difference type D promoted to the width of type T
328 typedef boost::uint128_type promoted_difference_type;
330 static boost::uint128_type min BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
334 static boost::uint128_type max BOOST_PREVENT_MACRO_SUBSTITUTION () BOOST_NOEXCEPT
336 return ~static_cast< boost::uint128_type >(0u);
340 #endif // defined(BOOST_HAS_INT128)
342 #if defined(BOOST_MSVC)
346 #if defined(BOOST_MSVC)
347 #pragma warning(push)
348 // unary minus operator applied to unsigned type, result still unsigned
349 #pragma warning(disable: 4146)
352 template< template< typename > class Wrapper, typename T, typename D, typename AddType >
353 void test_additive_operators_with_type_and_test()
356 // clang UBSAN flags this test when AddType is a pointer as it considers subtracting from a null pointer (zero_add) an UB
357 if (boost::is_pointer< AddType >::value)
361 // Note: This set of tests is extracted to a separate function because otherwise MSVC-10 for x64 generates broken code
362 typedef typename distance_limits< T, D >::promoted_difference_type promoted_difference_type;
363 typedef typename boost::make_unsigned< promoted_difference_type >::type unsigned_promoted_difference_type;
364 const T zero_value = 0;
365 const D zero_diff = 0;
366 const D one_diff = 1;
367 const AddType zero_add = 0;
369 Wrapper<T> wrapper(zero_value);
370 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
371 bool f = a.add_and_test(zero_diff);
372 BOOST_TEST_EQ( f, false );
373 BOOST_TEST_EQ( a.load(), zero_value );
375 f = a.add_and_test(one_diff);
376 BOOST_TEST_EQ( f, true );
377 BOOST_TEST_EQ( a.load(), T(zero_add + one_diff) );
380 Wrapper<T> wrapper(zero_value);
381 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
382 bool f = a.add_and_test((distance_limits< T, D >::max)());
383 BOOST_TEST_EQ( f, true );
384 BOOST_TEST_EQ( a.load(), T(zero_add + (distance_limits< T, D >::max)()) );
387 Wrapper<T> wrapper(zero_value);
388 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
389 bool f = a.add_and_test((distance_limits< T, D >::min)());
390 BOOST_TEST_EQ( f, ((distance_limits< T, D >::min)() != 0) );
391 BOOST_TEST_EQ( a.load(), T(zero_add + (distance_limits< T, D >::min)()) );
395 Wrapper<T> wrapper(zero_value);
396 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
397 bool f = a.sub_and_test(zero_diff);
398 BOOST_TEST_EQ( f, false );
399 BOOST_TEST_EQ( a.load(), zero_value );
401 f = a.sub_and_test(one_diff);
402 BOOST_TEST_EQ( f, true );
403 BOOST_TEST_EQ( a.load(), T(zero_add - one_diff) );
406 Wrapper<T> wrapper(zero_value);
407 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
408 bool f = a.sub_and_test((distance_limits< T, D >::max)());
409 BOOST_TEST_EQ( f, true );
410 BOOST_TEST_EQ( a.load(), T(zero_add - (distance_limits< T, D >::max)()) );
413 Wrapper<T> wrapper(zero_value);
414 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
415 bool f = a.sub_and_test((distance_limits< T, D >::min)());
416 BOOST_TEST_EQ( f, ((distance_limits< T, D >::min)() != 0) );
417 // Be very careful as to not cause signed overflow on negation
418 unsigned_promoted_difference_type umin = static_cast< unsigned_promoted_difference_type >(
419 static_cast< promoted_difference_type >((distance_limits< T, D >::min)()));
421 promoted_difference_type neg_min;
422 std::memcpy(&neg_min, &umin, sizeof(neg_min));
423 BOOST_TEST_EQ( a.load(), T(zero_add + neg_min) );
427 #if defined(BOOST_MSVC)
431 template< template< typename > class Wrapper, typename T, typename D, typename AddType >
432 void test_additive_operators_with_type(T value, D delta)
434 /* note: the tests explicitly cast the result of any addition
435 to the type to be tested to force truncation of the result to
436 the correct range in case of overflow */
440 Wrapper<T> wrapper(value);
441 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
442 T n = a.fetch_add(delta);
443 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
444 BOOST_TEST_EQ( n, value );
448 Wrapper<T> wrapper(value);
449 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
450 T n = a.fetch_sub(delta);
451 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
452 BOOST_TEST_EQ( n, value );
455 // add/sub with an immediate
457 Wrapper<T> wrapper(value);
458 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
459 T n = a.fetch_add(1);
460 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
461 BOOST_TEST_EQ( n, value );
465 Wrapper<T> wrapper(value);
466 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
467 T n = a.fetch_sub(1);
468 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
469 BOOST_TEST_EQ( n, value );
473 Wrapper<T> wrapper(value);
474 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
475 T n = a.fetch_add(76);
476 BOOST_TEST_EQ( a.load(), T((AddType)value + 76) );
477 BOOST_TEST_EQ( n, value );
481 Wrapper<T> wrapper(value);
482 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
483 T n = a.fetch_sub(76);
484 BOOST_TEST_EQ( a.load(), T((AddType)value - 76) );
485 BOOST_TEST_EQ( n, value );
488 if ((std::numeric_limits< D >::max)() >= 4097)
490 Wrapper<T> wrapper(value);
491 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
492 T n = a.fetch_add((D)4097);
493 BOOST_TEST_EQ( a.load(), T((AddType)value + (D)4097) );
494 BOOST_TEST_EQ( n, value );
497 if ((std::numeric_limits< D >::max)() >= 4097)
499 Wrapper<T> wrapper(value);
500 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
501 T n = a.fetch_sub((D)4097);
502 BOOST_TEST_EQ( a.load(), T((AddType)value - (D)4097) );
503 BOOST_TEST_EQ( n, value );
506 // overloaded modify/assign
508 Wrapper<T> wrapper(value);
509 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
511 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
512 BOOST_TEST_EQ( n, T((AddType)value + delta) );
516 Wrapper<T> wrapper(value);
517 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
519 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
520 BOOST_TEST_EQ( n, T((AddType)value - delta) );
523 // overloaded increment/decrement
525 Wrapper<T> wrapper(value);
526 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
528 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
529 BOOST_TEST_EQ( n, value );
533 Wrapper<T> wrapper(value);
534 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
536 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
537 BOOST_TEST_EQ( n, T((AddType)value + 1) );
541 Wrapper<T> wrapper(value);
542 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
544 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
545 BOOST_TEST_EQ( n, value );
549 Wrapper<T> wrapper(value);
550 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
552 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
553 BOOST_TEST_EQ( n, T((AddType)value - 1) );
556 // Operations returning the actual resulting value
558 Wrapper<T> wrapper(value);
559 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
561 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
562 BOOST_TEST_EQ( n, T((AddType)value + delta) );
566 Wrapper<T> wrapper(value);
567 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
569 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
570 BOOST_TEST_EQ( n, T((AddType)value - delta) );
573 // The same with an immediate
575 Wrapper<T> wrapper(value);
576 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
578 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
579 BOOST_TEST_EQ( n, T((AddType)value + 1) );
583 Wrapper<T> wrapper(value);
584 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
586 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
587 BOOST_TEST_EQ( n, T((AddType)value - 1) );
591 Wrapper<T> wrapper(value);
592 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
594 BOOST_TEST_EQ( a.load(), T((AddType)value + 76) );
595 BOOST_TEST_EQ( n, T((AddType)value + 76) );
599 Wrapper<T> wrapper(value);
600 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
602 BOOST_TEST_EQ( a.load(), T((AddType)value - 76) );
603 BOOST_TEST_EQ( n, T((AddType)value - 76) );
606 if ((std::numeric_limits< D >::max)() >= 4097)
608 Wrapper<T> wrapper(value);
609 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
610 T n = a.add((D)4097);
611 BOOST_TEST_EQ( a.load(), T((AddType)value + (D)4097) );
612 BOOST_TEST_EQ( n, T((AddType)value + (D)4097) );
615 if ((std::numeric_limits< D >::max)() >= 4097)
617 Wrapper<T> wrapper(value);
618 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
619 T n = a.sub((D)4097);
620 BOOST_TEST_EQ( a.load(), T((AddType)value - (D)4097) );
621 BOOST_TEST_EQ( n, T((AddType)value - (D)4097) );
626 Wrapper<T> wrapper(value);
627 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
629 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
633 Wrapper<T> wrapper(value);
634 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
636 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
639 // The same with an immediate
641 Wrapper<T> wrapper(value);
642 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
644 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
648 Wrapper<T> wrapper(value);
649 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
651 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
655 Wrapper<T> wrapper(value);
656 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
658 BOOST_TEST_EQ( a.load(), T((AddType)value + 76) );
662 Wrapper<T> wrapper(value);
663 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
665 BOOST_TEST_EQ( a.load(), T((AddType)value - 76) );
668 if ((std::numeric_limits< D >::max)() >= 4097)
670 Wrapper<T> wrapper(value);
671 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
672 a.opaque_add((D)4097);
673 BOOST_TEST_EQ( a.load(), T((AddType)value + (D)4097) );
676 if ((std::numeric_limits< D >::max)() >= 4097)
678 Wrapper<T> wrapper(value);
679 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
680 a.opaque_sub((D)4097);
681 BOOST_TEST_EQ( a.load(), T((AddType)value - (D)4097) );
684 // Modify and test operations
685 test_additive_operators_with_type_and_test< Wrapper, T, D, AddType >();
688 template< template< typename > class Wrapper, typename T, typename D >
689 void test_additive_operators(T value, D delta)
691 test_additive_operators_with_type< Wrapper, T, D, T >(value, delta);
694 template< template< typename > class Wrapper, typename T >
698 Wrapper<T> wrapper((T)1);
699 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
700 T n = a.fetch_negate();
701 BOOST_TEST_EQ( a.load(), (T)-1 );
702 BOOST_TEST_EQ( n, (T)1 );
704 n = a.fetch_negate();
705 BOOST_TEST_EQ( a.load(), (T)1 );
706 BOOST_TEST_EQ( n, (T)-1 );
709 Wrapper<T> wrapper((T)1);
710 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
712 BOOST_TEST_EQ( a.load(), (T)-1 );
713 BOOST_TEST_EQ( n, (T)-1 );
716 BOOST_TEST_EQ( a.load(), (T)1 );
717 BOOST_TEST_EQ( n, (T)1 );
720 Wrapper<T> wrapper((T)1);
721 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
723 BOOST_TEST_EQ( a.load(), (T)-1 );
726 BOOST_TEST_EQ( a.load(), (T)1 );
729 Wrapper<T> wrapper((T)1);
730 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
731 bool f = a.negate_and_test();
732 BOOST_TEST_EQ( f, true );
733 BOOST_TEST_EQ( a.load(), (T)-1 );
735 f = a.negate_and_test();
736 BOOST_TEST_EQ( f, true );
737 BOOST_TEST_EQ( a.load(), (T)1 );
740 Wrapper<T> wrapper((T)0);
741 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
742 bool f = a.negate_and_test();
743 BOOST_TEST_EQ( f, false );
744 BOOST_TEST_EQ( a.load(), (T)0 );
748 template< template< typename > class Wrapper, typename T >
749 void test_additive_wrap(T value)
752 Wrapper<T> wrapper(value);
753 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
754 T n = a.fetch_add(1) + (T)1;
755 BOOST_TEST_EQ( a.load(), n );
758 Wrapper<T> wrapper(value);
759 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
760 T n = a.fetch_sub(1) - (T)1;
761 BOOST_TEST_EQ( a.load(), n );
765 template< template< typename > class Wrapper, typename T >
766 void test_bit_operators(T value, T delta)
768 // explicit and/or/xor
770 Wrapper<T> wrapper(value);
771 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
772 T n = a.fetch_and(delta);
773 BOOST_TEST_EQ( a.load(), T(value & delta) );
774 BOOST_TEST_EQ( n, value );
778 Wrapper<T> wrapper(value);
779 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
780 T n = a.fetch_or(delta);
781 BOOST_TEST_EQ( a.load(), T(value | delta) );
782 BOOST_TEST_EQ( n, value );
786 Wrapper<T> wrapper(value);
787 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
788 T n = a.fetch_xor(delta);
789 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
790 BOOST_TEST_EQ( n, value );
794 Wrapper<T> wrapper(value);
795 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
796 T n = a.fetch_complement();
797 BOOST_TEST_EQ( a.load(), T(~value) );
798 BOOST_TEST_EQ( n, value );
801 // and/or/xor with an immediate. The immediates below are chosen to either be encodable in an instruction or not for various target architectures.
803 Wrapper<T> wrapper(value);
804 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
805 T n = a.fetch_and((T)1);
806 BOOST_TEST_EQ( a.load(), T(value & (T)1) );
807 BOOST_TEST_EQ( n, value );
811 Wrapper<T> wrapper(value);
812 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
813 T n = a.fetch_or((T)1);
814 BOOST_TEST_EQ( a.load(), T(value | (T)1) );
815 BOOST_TEST_EQ( n, value );
819 Wrapper<T> wrapper(value);
820 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
821 T n = a.fetch_xor((T)1);
822 BOOST_TEST_EQ( a.load(), T(value ^ (T)1) );
823 BOOST_TEST_EQ( n, value );
826 // The following constants are not encodable in AArch64
828 Wrapper<T> wrapper(value);
829 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
830 T n = a.fetch_and((T)76);
831 BOOST_TEST_EQ( a.load(), T(value & (T)76) );
832 BOOST_TEST_EQ( n, value );
836 Wrapper<T> wrapper(value);
837 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
838 T n = a.fetch_or((T)76);
839 BOOST_TEST_EQ( a.load(), T(value | (T)76) );
840 BOOST_TEST_EQ( n, value );
844 Wrapper<T> wrapper(value);
845 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
846 T n = a.fetch_xor((T)76);
847 BOOST_TEST_EQ( a.load(), T(value ^ (T)76) );
848 BOOST_TEST_EQ( n, value );
851 // overloaded modify/assign
853 Wrapper<T> wrapper(value);
854 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
856 BOOST_TEST_EQ( a.load(), T(value & delta) );
857 BOOST_TEST_EQ( n, T(value & delta) );
861 Wrapper<T> wrapper(value);
862 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
864 BOOST_TEST_EQ( a.load(), T(value | delta) );
865 BOOST_TEST_EQ( n, T(value | delta) );
869 Wrapper<T> wrapper(value);
870 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
872 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
873 BOOST_TEST_EQ( n, T(value ^ delta) );
876 // Operations returning the actual resulting value
878 Wrapper<T> wrapper(value);
879 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
880 T n = a.bitwise_and(delta);
881 BOOST_TEST_EQ( a.load(), T(value & delta) );
882 BOOST_TEST_EQ( n, T(value & delta) );
886 Wrapper<T> wrapper(value);
887 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
888 T n = a.bitwise_or(delta);
889 BOOST_TEST_EQ( a.load(), T(value | delta) );
890 BOOST_TEST_EQ( n, T(value | delta) );
894 Wrapper<T> wrapper(value);
895 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
896 T n = a.bitwise_xor(delta);
897 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
898 BOOST_TEST_EQ( n, T(value ^ delta) );
902 Wrapper<T> wrapper(value);
903 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
904 T n = a.bitwise_complement();
905 BOOST_TEST_EQ( a.load(), T(~value) );
906 BOOST_TEST_EQ( n, T(~value) );
909 // The same with an immediate
911 Wrapper<T> wrapper(value);
912 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
913 T n = a.bitwise_and((T)1);
914 BOOST_TEST_EQ( a.load(), T(value & (T)1) );
915 BOOST_TEST_EQ( n, T(value & (T)1) );
919 Wrapper<T> wrapper(value);
920 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
921 T n = a.bitwise_or((T)1);
922 BOOST_TEST_EQ( a.load(), T(value | (T)1) );
923 BOOST_TEST_EQ( n, T(value | (T)1) );
927 Wrapper<T> wrapper(value);
928 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
929 T n = a.bitwise_xor((T)1);
930 BOOST_TEST_EQ( a.load(), T(value ^ (T)1) );
931 BOOST_TEST_EQ( n, T(value ^ (T)1) );
934 // The following constants are not encodable in AArch64
936 Wrapper<T> wrapper(value);
937 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
938 T n = a.bitwise_and((T)76);
939 BOOST_TEST_EQ( a.load(), T(value & (T)76) );
940 BOOST_TEST_EQ( n, T(value & (T)76) );
944 Wrapper<T> wrapper(value);
945 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
946 T n = a.bitwise_or((T)76);
947 BOOST_TEST_EQ( a.load(), T(value | (T)76) );
948 BOOST_TEST_EQ( n, T(value | (T)76) );
952 Wrapper<T> wrapper(value);
953 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
954 T n = a.bitwise_xor((T)76);
955 BOOST_TEST_EQ( a.load(), T(value ^ (T)76) );
956 BOOST_TEST_EQ( n, T(value ^ (T)76) );
961 Wrapper<T> wrapper(value);
962 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
964 BOOST_TEST_EQ( a.load(), T(value & delta) );
968 Wrapper<T> wrapper(value);
969 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
971 BOOST_TEST_EQ( a.load(), T(value | delta) );
975 Wrapper<T> wrapper(value);
976 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
978 BOOST_TEST_EQ( a.load(), T(value ^ delta) );
982 Wrapper<T> wrapper(value);
983 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
984 a.opaque_complement();
985 BOOST_TEST_EQ( a.load(), T(~value) );
988 // The same with an immediate
990 Wrapper<T> wrapper(value);
991 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
993 BOOST_TEST_EQ( a.load(), T(value & (T)1) );
997 Wrapper<T> wrapper(value);
998 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1000 BOOST_TEST_EQ( a.load(), T(value | (T)1) );
1004 Wrapper<T> wrapper(value);
1005 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1007 BOOST_TEST_EQ( a.load(), T(value ^ (T)1) );
1010 // The following constants are not encodable in AArch64
1012 Wrapper<T> wrapper(value);
1013 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1014 a.opaque_and((T)76);
1015 BOOST_TEST_EQ( a.load(), T(value & (T)76) );
1019 Wrapper<T> wrapper(value);
1020 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1022 BOOST_TEST_EQ( a.load(), T(value | (T)76) );
1026 Wrapper<T> wrapper(value);
1027 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1028 a.opaque_xor((T)76);
1029 BOOST_TEST_EQ( a.load(), T(value ^ (T)76) );
1032 // Modify and test operations
1034 Wrapper<T> wrapper((T)1);
1035 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1036 bool f = a.and_and_test((T)1);
1037 BOOST_TEST_EQ( f, true );
1038 BOOST_TEST_EQ( a.load(), T(1) );
1040 f = a.and_and_test((T)0);
1041 BOOST_TEST_EQ( f, false );
1042 BOOST_TEST_EQ( a.load(), T(0) );
1044 f = a.and_and_test((T)0);
1045 BOOST_TEST_EQ( f, false );
1046 BOOST_TEST_EQ( a.load(), T(0) );
1050 Wrapper<T> wrapper((T)0);
1051 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1052 bool f = a.or_and_test((T)0);
1053 BOOST_TEST_EQ( f, false );
1054 BOOST_TEST_EQ( a.load(), T(0) );
1056 f = a.or_and_test((T)1);
1057 BOOST_TEST_EQ( f, true );
1058 BOOST_TEST_EQ( a.load(), T(1) );
1060 f = a.or_and_test((T)1);
1061 BOOST_TEST_EQ( f, true );
1062 BOOST_TEST_EQ( a.load(), T(1) );
1066 Wrapper<T> wrapper((T)0);
1067 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1068 bool f = a.xor_and_test((T)0);
1069 BOOST_TEST_EQ( f, false );
1070 BOOST_TEST_EQ( a.load(), T(0) );
1072 f = a.xor_and_test((T)1);
1073 BOOST_TEST_EQ( f, true );
1074 BOOST_TEST_EQ( a.load(), T(1) );
1076 f = a.xor_and_test((T)1);
1077 BOOST_TEST_EQ( f, false );
1078 BOOST_TEST_EQ( a.load(), T(0) );
1082 Wrapper<T> wrapper((T)0);
1083 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1084 bool f = a.complement_and_test();
1085 BOOST_TEST_EQ( f, true );
1086 BOOST_TEST_EQ( a.load(), static_cast< T >(~static_cast< T >(0)) );
1088 f = a.complement_and_test();
1089 BOOST_TEST_EQ( f, false );
1090 BOOST_TEST_EQ( a.load(), T(0) );
1093 // Bit test and modify operations
1095 Wrapper<T> wrapper((T)42);
1096 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1097 bool f = a.bit_test_and_set(0);
1098 BOOST_TEST_EQ( f, false );
1099 BOOST_TEST_EQ( a.load(), T(43) );
1101 f = a.bit_test_and_set(1);
1102 BOOST_TEST_EQ( f, true );
1103 BOOST_TEST_EQ( a.load(), T(43) );
1105 f = a.bit_test_and_set(2);
1106 BOOST_TEST_EQ( f, false );
1107 BOOST_TEST_EQ( a.load(), T(47) );
1111 Wrapper<T> wrapper((T)42);
1112 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1113 bool f = a.bit_test_and_reset(0);
1114 BOOST_TEST_EQ( f, false );
1115 BOOST_TEST_EQ( a.load(), T(42) );
1117 f = a.bit_test_and_reset(1);
1118 BOOST_TEST_EQ( f, true );
1119 BOOST_TEST_EQ( a.load(), T(40) );
1121 f = a.bit_test_and_set(2);
1122 BOOST_TEST_EQ( f, false );
1123 BOOST_TEST_EQ( a.load(), T(44) );
1127 Wrapper<T> wrapper((T)42);
1128 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1129 bool f = a.bit_test_and_complement(0);
1130 BOOST_TEST_EQ( f, false );
1131 BOOST_TEST_EQ( a.load(), T(43) );
1133 f = a.bit_test_and_complement(1);
1134 BOOST_TEST_EQ( f, true );
1135 BOOST_TEST_EQ( a.load(), T(41) );
1137 f = a.bit_test_and_complement(2);
1138 BOOST_TEST_EQ( f, false );
1139 BOOST_TEST_EQ( a.load(), T(45) );
1142 // Test that a runtime value works for the bit index. This is important for asm block constraints.
1144 unsigned int runtime_bit_index = std::rand() & 7u;
1145 Wrapper<T> wrapper((T)42);
1146 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1148 a.bit_test_and_set(runtime_bit_index);
1149 a.bit_test_and_reset(runtime_bit_index);
1150 a.bit_test_and_complement(runtime_bit_index);
1154 template< template< typename > class Wrapper, typename T >
1155 void do_test_integral_api(boost::false_type)
1157 test_base_operators< Wrapper, T >(42, 43, 44);
1158 test_additive_operators< Wrapper, T, T >(42, 17);
1159 test_bit_operators< Wrapper, T >((T)0x5f5f5f5f5f5f5f5fULL, (T)0xf5f5f5f5f5f5f5f5ULL);
1161 /* test for unsigned overflow/underflow */
1162 test_additive_operators< Wrapper, T, T >((T)-1, 1);
1163 test_additive_operators< Wrapper, T, T >(0, 1);
1164 /* test for signed overflow/underflow */
1165 test_additive_operators< Wrapper, T, T >(((T)-1) >> (sizeof(T) * 8 - 1), 1);
1166 test_additive_operators< Wrapper, T, T >(1 + (((T)-1) >> (sizeof(T) * 8 - 1)), 1);
1169 template< template< typename > class Wrapper, typename T >
1170 void do_test_integral_api(boost::true_type)
1172 do_test_integral_api< Wrapper, T >(boost::false_type());
1174 test_additive_wrap< Wrapper, T >(0u);
1175 BOOST_CONSTEXPR_OR_CONST T all_ones = ~(T)0u;
1176 test_additive_wrap< Wrapper, T >(all_ones);
1177 BOOST_CONSTEXPR_OR_CONST T max_signed_twos_compl = all_ones >> 1;
1178 test_additive_wrap< Wrapper, T >(all_ones ^ max_signed_twos_compl);
1179 test_additive_wrap< Wrapper, T >(max_signed_twos_compl);
1182 template< template< typename > class Wrapper, typename T >
1183 inline void test_integral_api(void)
1185 do_test_integral_api< Wrapper, T >(boost::is_unsigned<T>());
1187 if (boost::is_signed<T>::value)
1188 test_negation< Wrapper, T >();
1191 template< template< typename > class Wrapper, typename T >
1192 inline void test_lock_free_integral_api(boost::true_type)
1194 test_integral_api< Wrapper, T >();
1197 template< template< typename > class Wrapper, typename T >
1198 inline void test_lock_free_integral_api(boost::false_type)
1202 template< template< typename > class Wrapper, typename T >
1203 inline void test_lock_free_integral_api(void)
1205 test_lock_free_integral_api< Wrapper, T >(boost::integral_constant< bool, Wrapper< T >::atomic_type::is_always_lock_free >());
1208 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
1210 template< template< typename > class Wrapper, typename T, typename D >
1211 void test_fp_additive_operators(T value, D delta)
1215 Wrapper<T> wrapper(value);
1216 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1217 T n = a.fetch_add(delta);
1218 BOOST_TEST_EQ( a.load(), approx(T(value + delta)) );
1219 BOOST_TEST_EQ( n, approx(value) );
1223 Wrapper<T> wrapper(value);
1224 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1225 T n = a.fetch_sub(delta);
1226 BOOST_TEST_EQ( a.load(), approx(T(value - delta)) );
1227 BOOST_TEST_EQ( n, approx(value) );
1230 // overloaded modify/assign
1232 Wrapper<T> wrapper(value);
1233 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1235 BOOST_TEST_EQ( a.load(), approx(T(value + delta)) );
1236 BOOST_TEST_EQ( n, approx(T(value + delta)) );
1240 Wrapper<T> wrapper(value);
1241 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1243 BOOST_TEST_EQ( a.load(), approx(T(value - delta)) );
1244 BOOST_TEST_EQ( n, approx(T(value - delta)) );
1247 // Operations returning the actual resulting value
1249 Wrapper<T> wrapper(value);
1250 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1252 BOOST_TEST_EQ( a.load(), approx(T(value + delta)) );
1253 BOOST_TEST_EQ( n, approx(T(value + delta)) );
1257 Wrapper<T> wrapper(value);
1258 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1260 BOOST_TEST_EQ( a.load(), approx(T(value - delta)) );
1261 BOOST_TEST_EQ( n, approx(T(value - delta)) );
1264 // Opaque operations
1266 Wrapper<T> wrapper(value);
1267 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1268 a.opaque_add(delta);
1269 BOOST_TEST_EQ( a.load(), approx(T(value + delta)) );
1273 Wrapper<T> wrapper(value);
1274 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1275 a.opaque_sub(delta);
1276 BOOST_TEST_EQ( a.load(), approx(T(value - delta)) );
1280 template< template< typename > class Wrapper, typename T >
1281 void test_fp_negation()
1284 Wrapper<T> wrapper((T)1);
1285 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1286 T n = a.fetch_negate();
1287 BOOST_TEST_EQ( a.load(), approx((T)-1) );
1288 BOOST_TEST_EQ( n, approx((T)1) );
1290 n = a.fetch_negate();
1291 BOOST_TEST_EQ( a.load(), approx((T)1) );
1292 BOOST_TEST_EQ( n, approx((T)-1) );
1295 Wrapper<T> wrapper((T)1);
1296 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1298 BOOST_TEST_EQ( a.load(), approx((T)-1) );
1299 BOOST_TEST_EQ( n, approx((T)-1) );
1302 BOOST_TEST_EQ( a.load(), approx((T)1) );
1303 BOOST_TEST_EQ( n, approx((T)1) );
1306 Wrapper<T> wrapper((T)1);
1307 typename Wrapper<T>::atomic_reference_type a = wrapper.a;
1309 BOOST_TEST_EQ( a.load(), approx((T)-1) );
1312 BOOST_TEST_EQ( a.load(), approx((T)1) );
1316 #endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
1318 template< template< typename > class Wrapper, typename T >
1319 void test_floating_point_api(void)
1321 // Note: When support for floating point is disabled, even the base operation tests may fail because
1322 // the generic template specialization does not account for garbage in padding bits that are present in some FP types.
1323 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
1324 test_base_operators< Wrapper, T >(static_cast<T>(42.1), static_cast<T>(43.2), static_cast<T>(44.3));
1326 test_fp_additive_operators< Wrapper, T, T >(static_cast<T>(42.5), static_cast<T>(17.7));
1327 test_fp_additive_operators< Wrapper, T, T >(static_cast<T>(-42.5), static_cast<T>(-17.7));
1329 test_fp_negation< Wrapper, T >();
1333 template< template< typename > class Wrapper, typename T >
1334 inline void test_lock_free_floating_point_api(boost::true_type)
1336 test_floating_point_api< Wrapper, T >();
1339 template< template< typename > class Wrapper, typename T >
1340 inline void test_lock_free_floating_point_api(boost::false_type)
1344 template< template< typename > class Wrapper, typename T >
1345 inline void test_lock_free_floating_point_api(void)
1347 test_lock_free_floating_point_api< Wrapper, T >(boost::integral_constant< bool, Wrapper< T >::atomic_type::is_always_lock_free >());
1351 template< template< typename > class Wrapper, typename T >
1352 void test_pointer_api(void)
1354 std::vector< T > values;
1355 values.resize(5000); // make the vector large enough to accommodate pointer arithmetics in the additive tests
1357 test_base_operators< Wrapper, T* >(&values[0], &values[1], &values[2]);
1358 test_additive_operators< Wrapper, T* >(&values[1], 1);
1360 test_base_operators< Wrapper, void* >(&values[0], &values[1], &values[2]);
1362 #if defined(BOOST_HAS_INTPTR_T)
1363 Wrapper<void*> wrapper_ptr;
1364 typename Wrapper<void*>::atomic_reference_type ptr = wrapper_ptr.a;
1365 Wrapper<boost::intptr_t> wrapper_integral;
1366 typename Wrapper<boost::intptr_t>::atomic_reference_type integral = wrapper_integral.a;
1367 BOOST_TEST_EQ( ptr.is_lock_free(), integral.is_lock_free() );
1376 template< template< typename > class Wrapper, typename T >
1377 inline void test_lock_free_pointer_api(boost::true_type)
1379 test_pointer_api< Wrapper, T >();
1382 template< template< typename > class Wrapper, typename T >
1383 inline void test_lock_free_pointer_api(boost::false_type)
1387 template< template< typename > class Wrapper, typename T >
1388 inline void test_lock_free_pointer_api(void)
1390 test_lock_free_pointer_api< Wrapper, T >(boost::integral_constant< bool, Wrapper< T >::atomic_type::is_always_lock_free >());
1394 template< template< typename > class Wrapper >
1395 void test_enum_api(void)
1397 test_base_operators< Wrapper >(foo, bar, baz);
1400 template< template< typename > class Wrapper >
1401 inline void test_lock_free_enum_api(boost::true_type)
1403 test_enum_api< Wrapper >();
1406 template< template< typename > class Wrapper >
1407 inline void test_lock_free_enum_api(boost::false_type)
1411 template< template< typename > class Wrapper >
1412 inline void test_lock_free_enum_api(void)
1414 test_lock_free_enum_api< Wrapper >(boost::integral_constant< bool, Wrapper< test_enum >::atomic_type::is_always_lock_free >());
1418 template< typename T >
1421 typedef T value_type;
1423 inline bool operator==(test_struct const& c) const { return i == c.i; }
1424 inline bool operator!=(test_struct const& c) const { return !operator==(c); }
1427 template< typename Char, typename Traits, typename T >
1428 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct< T > const& s)
1430 test_stream << "{" << s.i << "}";
1434 template< template< typename > class Wrapper, typename T >
1435 void test_struct_api(void)
1437 T a = {1}, b = {2}, c = {3};
1439 test_base_operators< Wrapper >(a, b, c);
1442 Wrapper<T> wrapper_sa;
1443 typename Wrapper<T>::atomic_reference_type sa = wrapper_sa.a;
1444 Wrapper<typename T::value_type> wrapper_si;
1445 typename Wrapper<typename T::value_type>::atomic_reference_type si = wrapper_si.a;
1446 BOOST_TEST_EQ( sa.is_lock_free(), si.is_lock_free() );
1450 template< typename T >
1451 struct test_struct_x2
1453 typedef T value_type;
1455 inline bool operator==(test_struct_x2 const& c) const { return i == c.i && j == c.j; }
1456 inline bool operator!=(test_struct_x2 const& c) const { return !operator==(c); }
1459 template< typename Char, typename Traits, typename T >
1460 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct_x2< T > const& s)
1462 test_stream << "{" << s.i << ", " << s.j << "}";
1466 template< template< typename > class Wrapper, typename T >
1467 void test_struct_x2_api(void)
1469 T a = {1, 1}, b = {2, 2}, c = {3, 3};
1471 test_base_operators< Wrapper >(a, b, c);
1476 unsigned char data[256u];
1478 inline bool operator==(large_struct const& c) const
1480 return std::memcmp(data, &c.data, sizeof(data)) == 0;
1482 inline bool operator!=(large_struct const& c) const
1484 return std::memcmp(data, &c.data, sizeof(data)) != 0;
1488 template< typename Char, typename Traits >
1489 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, large_struct const&)
1491 strm << "[large_struct]";
1495 template< template< typename > class Wrapper >
1496 void test_large_struct_api(void)
1498 large_struct a = {{1}}, b = {{2}}, c = {{3}};
1499 test_base_operators< Wrapper >(a, b, c);
1502 struct test_struct_with_ctor
1504 typedef unsigned int value_type;
1506 test_struct_with_ctor() : i(0x01234567) {}
1507 inline bool operator==(test_struct_with_ctor const& c) const { return i == c.i; }
1508 inline bool operator!=(test_struct_with_ctor const& c) const { return !operator==(c); }
1511 template< typename Char, typename Traits >
1512 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct_with_ctor const& s)
1514 strm << "{" << s.i << "}";
1518 template< template< typename > class Wrapper >
1519 void test_struct_with_ctor_api(void)
1521 test_struct_with_ctor a, b, c;
1526 test_base_operators< Wrapper >(a, b, c);
1529 #if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING)
1531 struct test_struct_with_padding
1536 inline bool operator==(test_struct_with_padding const& s) const { return c == s.c && n == s.n; }
1537 inline bool operator!=(test_struct_with_padding const& s) const { return !operator==(s); }
1540 template< typename Char, typename Traits >
1541 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, test_struct_with_padding const& s)
1543 strm << "{" << static_cast< unsigned int >(s.c) << ", " << static_cast< unsigned int >(s.n) << "}";
1548 template< template< typename > class Wrapper >
1549 void test_struct_with_padding_api(void)
1551 union test_struct_with_padding_init
1553 unsigned char as_bytes[sizeof(test_struct_with_padding)];
1554 test_struct_with_padding as_struct;
1558 for (unsigned int i = 0u; i < sizeof(a.as_bytes) / sizeof(*a.as_bytes); ++i)
1560 a.as_bytes[i] = static_cast< unsigned char >(i + 0xA0);
1561 b.as_bytes[i] = static_cast< unsigned char >(i + 0xB0);
1562 c.as_bytes[i] = static_cast< unsigned char >(i + 0xC0);
1565 a.as_struct.c = 10u;
1566 a.as_struct.n = 1000u;
1567 b.as_struct.c = 11u;
1568 b.as_struct.n = 1001u;
1569 c.as_struct.c = 12u;
1570 c.as_struct.n = 1002u;
1572 test_base_operators< Wrapper >(a.as_struct, b.as_struct, c.as_struct);
1575 #endif // !defined(BOOST_ATOMIC_NO_CLEAR_PADDING)
1577 #endif // BOOST_ATOMIC_API_TEST_HELPERS_HPP