]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
7c673cae 1// Copyright (c) 2011 Helge Bahmann
b32b8144 2// Copyright (c) 2017 Andrey Semashev
7c673cae
FG
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>
b32b8144 12#include <cstddef>
7c673cae 13#include <cstring>
b32b8144
FG
14#include <limits>
15#include <iostream>
7c673cae
FG
16#include <boost/config.hpp>
17#include <boost/cstdint.hpp>
7c673cae 18#include <boost/type_traits/integral_constant.hpp>
b32b8144 19#include <boost/type_traits/is_signed.hpp>
7c673cae
FG
20#include <boost/type_traits/is_unsigned.hpp>
21
b32b8144
FG
22struct 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
93const test_stream_type test_stream = {};
94
95#define BOOST_LIGHTWEIGHT_TEST_OSTREAM test_stream
96
97#include <boost/core/lightweight_test.hpp>
98
7c673cae
FG
99/* provide helpers that exercise whether the API
100functions of "boost::atomic" provide the correct
101operational semantic in the case of sequential
102execution */
103
104static void
105test_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
119template<typename T>
120void test_base_operators(T value1, T value2, T value3)
121{
122 /* explicit load/store */
123 {
124 boost::atomic<T> a(value1);
b32b8144 125 BOOST_TEST_EQ( a.load(), value1 );
7c673cae
FG
126 }
127
128 {
129 boost::atomic<T> a(value1);
130 a.store(value2);
b32b8144 131 BOOST_TEST_EQ( a.load(), value2 );
7c673cae
FG
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);
b32b8144
FG
150 BOOST_TEST_EQ( a.load(), value2 );
151 BOOST_TEST_EQ( n, value1 );
7c673cae
FG
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 );
b32b8144
FG
159 BOOST_TEST_EQ( a.load(), value3 );
160 BOOST_TEST_EQ( expected, value1 );
7c673cae
FG
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 );
b32b8144
FG
168 BOOST_TEST_EQ( a.load(), value1 );
169 BOOST_TEST_EQ( expected, value1 );
7c673cae
FG
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 );
b32b8144
FG
181 BOOST_TEST_EQ( a.load(), value3 );
182 BOOST_TEST_EQ( expected, value1 );
7c673cae
FG
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 );
b32b8144
FG
196 BOOST_TEST_EQ( a.load(), value1 );
197 BOOST_TEST_EQ( expected, value1 );
7c673cae
FG
198 }
199}
200
201// T requires an int constructor
202template <typename T>
203void 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
b32b8144
FG
212//! The type traits provides max and min values of type D that can be added/subtracted to T(0) without signed overflow
213template< typename T, typename D, bool IsSigned = boost::is_signed< D >::value >
214struct 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
233template< typename T, typename D >
234struct 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
252template< typename T, typename D >
253struct 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.
271template< typename T, bool IsSigned >
272struct 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
284template< typename T, bool IsSigned >
285struct 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
303template<typename T, typename D, typename AddType>
304void 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
7c673cae
FG
358template<typename T, typename D, typename AddType>
359void 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);
b32b8144
FG
369 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
370 BOOST_TEST_EQ( n, value );
7c673cae
FG
371 }
372
373 {
374 boost::atomic<T> a(value);
375 T n = a.fetch_sub(delta);
b32b8144
FG
376 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
377 BOOST_TEST_EQ( n, value );
7c673cae
FG
378 }
379
380 /* overloaded modify/assign*/
381 {
382 boost::atomic<T> a(value);
383 T n = (a += delta);
b32b8144
FG
384 BOOST_TEST_EQ( a.load(), T((AddType)value + delta) );
385 BOOST_TEST_EQ( n, T((AddType)value + delta) );
7c673cae
FG
386 }
387
388 {
389 boost::atomic<T> a(value);
390 T n = (a -= delta);
b32b8144
FG
391 BOOST_TEST_EQ( a.load(), T((AddType)value - delta) );
392 BOOST_TEST_EQ( n, T((AddType)value - delta) );
7c673cae
FG
393 }
394
395 /* overloaded increment/decrement */
396 {
397 boost::atomic<T> a(value);
398 T n = a++;
b32b8144
FG
399 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
400 BOOST_TEST_EQ( n, value );
7c673cae
FG
401 }
402
403 {
404 boost::atomic<T> a(value);
405 T n = ++a;
b32b8144
FG
406 BOOST_TEST_EQ( a.load(), T((AddType)value + 1) );
407 BOOST_TEST_EQ( n, T((AddType)value + 1) );
7c673cae
FG
408 }
409
410 {
411 boost::atomic<T> a(value);
412 T n = a--;
b32b8144
FG
413 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
414 BOOST_TEST_EQ( n, value );
7c673cae
FG
415 }
416
417 {
418 boost::atomic<T> a(value);
419 T n = --a;
b32b8144
FG
420 BOOST_TEST_EQ( a.load(), T((AddType)value - 1) );
421 BOOST_TEST_EQ( n, T((AddType)value - 1) );
7c673cae 422 }
b32b8144
FG
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 >();
7c673cae
FG
439}
440
441template<typename T, typename D>
442void test_additive_operators(T value, D delta)
443{
444 test_additive_operators_with_type<T, D, T>(value, delta);
445}
446
b32b8144
FG
447template< typename T >
448void 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
7c673cae
FG
470template<typename T>
471void test_additive_wrap(T value)
472{
473 {
474 boost::atomic<T> a(value);
b32b8144
FG
475 T n = a.fetch_add(1) + (T)1;
476 BOOST_TEST_EQ( a.load(), n );
7c673cae
FG
477 }
478 {
479 boost::atomic<T> a(value);
b32b8144
FG
480 T n = a.fetch_sub(1) - (T)1;
481 BOOST_TEST_EQ( a.load(), n );
7c673cae
FG
482 }
483}
484
485template<typename T>
486void 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);
b32b8144
FG
492 BOOST_TEST_EQ( a.load(), T(value & delta) );
493 BOOST_TEST_EQ( n, value );
7c673cae
FG
494 }
495
496 {
497 boost::atomic<T> a(value);
498 T n = a.fetch_or(delta);
b32b8144
FG
499 BOOST_TEST_EQ( a.load(), T(value | delta) );
500 BOOST_TEST_EQ( n, value );
7c673cae
FG
501 }
502
503 {
504 boost::atomic<T> a(value);
505 T n = a.fetch_xor(delta);
b32b8144
FG
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 );
7c673cae
FG
515 }
516
517 /* overloaded modify/assign */
518 {
519 boost::atomic<T> a(value);
520 T n = (a &= delta);
b32b8144
FG
521 BOOST_TEST_EQ( a.load(), T(value & delta) );
522 BOOST_TEST_EQ( n, T(value & delta) );
7c673cae
FG
523 }
524
525 {
526 boost::atomic<T> a(value);
527 T n = (a |= delta);
b32b8144
FG
528 BOOST_TEST_EQ( a.load(), T(value | delta) );
529 BOOST_TEST_EQ( n, T(value | delta) );
7c673cae
FG
530 }
531
532 {
533 boost::atomic<T> a(value);
534 T n = (a ^= delta);
b32b8144
FG
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) );
7c673cae
FG
654 }
655}
656
657template<typename T>
658void 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
674template<typename T>
675void do_test_integral_api(boost::true_type)
676{
677 do_test_integral_api<T>(boost::false_type());
678
679 test_additive_wrap<T>(0u);
b32b8144
FG
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);
7c673cae
FG
685}
686
687template<typename T>
688inline void test_integral_api(void)
689{
690 do_test_integral_api<T>(boost::is_unsigned<T>());
b32b8144
FG
691
692 if (boost::is_signed<T>::value)
693 test_negation<T>();
7c673cae
FG
694}
695
696template<typename T>
697void test_pointer_api(void)
698{
b32b8144
FG
699 BOOST_TEST_GE( sizeof(boost::atomic<T *>), sizeof(T *));
700 BOOST_TEST_GE( sizeof(boost::atomic<void *>), sizeof(T *));
7c673cae
FG
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]);
7c673cae
FG
708
709#if defined(BOOST_HAS_INTPTR_T)
710 boost::atomic<void *> ptr;
711 boost::atomic<boost::intptr_t> integral;
b32b8144 712 BOOST_TEST_EQ( ptr.is_lock_free(), integral.is_lock_free() );
7c673cae
FG
713#endif
714}
715
b32b8144
FG
716enum test_enum
717{
7c673cae
FG
718 foo, bar, baz
719};
720
721static void
722test_enum_api(void)
723{
724 test_base_operators(foo, bar, baz);
725}
726
727template<typename T>
b32b8144
FG
728struct test_struct
729{
7c673cae
FG
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
b32b8144
FG
736template< typename Char, typename Traits, typename T >
737inline 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
7c673cae
FG
743template<typename T>
744void
745test_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;
b32b8144 754 BOOST_TEST_EQ( sa.is_lock_free(), si.is_lock_free() );
7c673cae
FG
755 }
756}
757
758template<typename T>
b32b8144
FG
759struct test_struct_x2
760{
7c673cae
FG
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
b32b8144
FG
767template< typename Char, typename Traits, typename T >
768inline 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
7c673cae
FG
774template<typename T>
775void
776test_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
b32b8144
FG
783struct large_struct
784{
7c673cae
FG
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
b32b8144
FG
797template< typename Char, typename Traits >
798inline 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
7c673cae
FG
804static void
805test_large_struct_api(void)
806{
807 large_struct a = {{1}}, b = {{2}}, c = {{3}};
808 test_base_operators(a, b, c);
809}
810
b32b8144
FG
811struct test_struct_with_ctor
812{
7c673cae
FG
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
b32b8144
FG
820template< typename Char, typename Traits >
821inline 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
7c673cae
FG
827static void
828test_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