Fixed some minor compiler warnings
[libcds.git] / test / unit / misc / cxx11_atomic_func.cpp
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <gtest/gtest.h>
32 #include <cds/algo/atomic.h>
33
34 #ifndef CDS_USE_BOOST_ATOMIC
35 // Skip this test for boost.atomic
36 // Boost.atomic has no free atomic functions implementation.
37
38 #include "cxx11_convert_memory_order.h"
39
40 namespace misc {
41
42     class cxx11_atomic_func: public ::testing::Test
43     {
44     protected:
45         template <typename AtomicFlag>
46         void do_test_atomic_flag_mo( AtomicFlag& f, atomics::memory_order order )
47         {
48             atomics::memory_order mo_clear = convert_to_store_order(order);
49
50             f.clear( convert_to_store_order(order));
51
52             for ( int i = 0; i < 5; ++i ) {
53                 EXPECT_FALSE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
54                 EXPECT_TRUE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
55                 atomics::atomic_flag_clear_explicit( &f, mo_clear );
56                 atomics::atomic_flag_clear_explicit( &f, mo_clear );
57             }
58         }
59
60         template <typename AtomicFlag>
61         void do_test_atomic_flag( AtomicFlag& f )
62         {
63             f.clear();
64
65             for ( int i = 0; i < 5; ++i ) {
66                 EXPECT_FALSE( atomics::atomic_flag_test_and_set( &f ));
67                 EXPECT_TRUE( atomics::atomic_flag_test_and_set( &f ));
68                 atomics::atomic_flag_clear(&f);
69                 atomics::atomic_flag_clear(&f);
70             }
71
72             do_test_atomic_flag_mo( f, atomics::memory_order_relaxed );
73             do_test_atomic_flag_mo( f, atomics::memory_order_acquire );
74             do_test_atomic_flag_mo( f, atomics::memory_order_release );
75             do_test_atomic_flag_mo( f, atomics::memory_order_acq_rel );
76             do_test_atomic_flag_mo( f, atomics::memory_order_seq_cst );
77         }
78
79         template <class Atomic, typename Integral>
80         void do_test_atomic_type(Atomic& a )
81         {
82             typedef Integral    integral_type;
83
84             EXPECT_TRUE( atomics::atomic_is_lock_free( &a ));
85             atomics::atomic_store( &a, (integral_type) 0 );
86             //EXPECT_EQ( a, integral_type( 0 ));
87             EXPECT_EQ( atomics::atomic_load( &a ), integral_type( 0 ));
88
89             for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
90                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
91                 EXPECT_EQ( atomics::atomic_exchange( &a, n ), (integral_type) 0 );
92                 EXPECT_EQ( atomics::atomic_load( &a ), n );
93                 EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), n );
94                 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
95             }
96
97             integral_type prev = atomics::atomic_load( &a );
98             for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
99                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
100                 integral_type expected = prev;
101
102                 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
103                 EXPECT_EQ( expected, prev );
104                 EXPECT_NE( expected, n );
105                 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
106                 EXPECT_EQ( expected, n );
107
108                 prev = n;
109                 EXPECT_EQ( atomics::atomic_load( &a ), n );
110             }
111
112             atomics::atomic_store( &a, (integral_type) 0 );
113
114             prev = atomics::atomic_load( &a );
115             for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
116                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
117                 integral_type expected = prev;
118
119                 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
120                 EXPECT_EQ( expected, prev );
121                 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
122                 EXPECT_EQ( expected, n );
123
124                 prev = n;
125                 EXPECT_EQ( atomics::atomic_load( &a ), n );
126             }
127
128             EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), prev );
129         }
130
131         template <class Atomic, typename Integral>
132         void do_test_atomic_integral( Atomic& a )
133         {
134             do_test_atomic_type< Atomic, Integral >( a );
135
136             typedef Integral    integral_type;
137
138             // fetch_xxx testing
139             atomics::atomic_store( &a, (integral_type) 0 );
140
141             // fetch_add
142             for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
143             {
144                 integral_type prev = atomics::atomic_load( &a );
145                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
146
147                 EXPECT_EQ( atomics::atomic_fetch_add( &a, n ), prev );
148             }
149
150             // fetch_sub
151             for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
152             {
153                 integral_type prev = atomics::atomic_load( &a );
154                 integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
155
156                 EXPECT_EQ( atomics::atomic_fetch_sub( &a, n ), prev );
157             }
158             EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
159
160             // fetch_or / fetc_xor / fetch_and
161             for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
162             {
163                 integral_type prev = atomics::atomic_load( &a );
164                 integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
165
166                 EXPECT_EQ( atomics::atomic_fetch_or( &a, mask ), prev );
167                 prev = atomics::atomic_load( &a );
168                 EXPECT_EQ( ( prev & mask ), mask );
169
170                 EXPECT_EQ( atomics::atomic_fetch_and( &a, (integral_type) ~mask ), prev );
171                 prev = atomics::atomic_load( &a );
172                 EXPECT_EQ( integral_type(prev & mask), integral_type(0));
173
174                 EXPECT_EQ( atomics::atomic_fetch_xor( &a, mask ), prev );
175                 prev = atomics::atomic_load( &a );
176                 EXPECT_EQ( ( prev & mask), mask);
177             }
178             EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) -1 );
179         }
180
181         template <class Atomic, typename Integral>
182         void do_test_atomic_type( Atomic& a, atomics::memory_order order )
183         {
184             typedef Integral    integral_type;
185
186             const atomics::memory_order oLoad = convert_to_load_order( order );
187             const atomics::memory_order oStore = convert_to_store_order( order );
188
189             EXPECT_TRUE( atomics::atomic_is_lock_free( &a ));
190             atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
191             //EXPECT_EQ( a, integral_type( 0 ));
192             EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
193
194             for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
195                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
196                 EXPECT_EQ( atomics::atomic_exchange_explicit( &a, n, order ), (integral_type) 0 );
197                 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
198                 EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), n );
199                 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
200             }
201
202             integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
203             for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
204                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
205                 integral_type expected = prev;
206
207                 EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
208                 EXPECT_EQ( expected, prev );
209                 EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
210                 EXPECT_EQ( expected, n );
211
212                 prev = n;
213                 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
214             }
215
216             atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
217
218             prev = atomics::atomic_load_explicit( &a, oLoad );
219             for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
220                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
221                 integral_type expected = prev;
222
223                 EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
224                 EXPECT_EQ( expected, prev );
225                 EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
226                 EXPECT_EQ( expected, n );
227
228                 prev = n;
229                 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
230             }
231
232             EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), prev );
233         }
234
235         template <class Atomic, typename Integral>
236         void do_test_atomic_integral( Atomic& a, atomics::memory_order order )
237         {
238             do_test_atomic_type< Atomic, Integral >( a, order );
239             typedef Integral    integral_type;
240
241             const atomics::memory_order oLoad = convert_to_load_order( order );
242             const atomics::memory_order oStore = convert_to_store_order( order );
243
244             // fetch_xxx testing
245             atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
246
247             // fetch_add
248             for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
249             {
250                 integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
251                 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
252
253                 EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, n, order), prev);
254             }
255
256             // fetch_sub
257             for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
258             {
259                 integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
260                 integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
261
262                 EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, n, order ), prev);
263             }
264             EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), integral_type( 0 ));
265
266             // fetch_or / fetc_xor / fetch_and
267             for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
268             {
269                 integral_type prev = atomics::atomic_load_explicit( &a, oLoad )  ;;
270                 integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
271
272                 EXPECT_EQ( atomics::atomic_fetch_or_explicit( &a, mask, order ), prev );
273                 prev = atomics::atomic_load_explicit( &a, oLoad );
274                 EXPECT_EQ( ( prev & mask), mask);
275
276                 EXPECT_EQ( atomics::atomic_fetch_and_explicit( &a, (integral_type) ~mask, order ), prev );
277                 prev = atomics::atomic_load_explicit( &a, oLoad );
278                 EXPECT_EQ( ( prev & mask), integral_type( 0 ));
279
280                 EXPECT_EQ( atomics::atomic_fetch_xor_explicit( &a, mask, order ), prev );
281                 prev = atomics::atomic_load_explicit( &a, oLoad );
282                 EXPECT_EQ( ( prev & mask), mask);
283             }
284             EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) -1 );
285         }
286
287         template <typename Atomic, typename Integral>
288         void test_atomic_integral_(Atomic& a)
289         {
290             do_test_atomic_integral<Atomic, Integral >(a);
291
292             do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_relaxed );
293             do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acquire );
294             do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_release );
295             do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acq_rel );
296             do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_seq_cst );
297         }
298
299         template <typename Integral>
300         void test_atomic_integral()
301         {
302             typedef atomics::atomic<Integral>    atomic_type;
303             atomic_type a[8];
304             for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
305                 test_atomic_integral_<atomic_type, Integral>( a[i] );
306             }
307         }
308         template <typename Integral>
309         void test_atomic_integral_volatile()
310         {
311             typedef atomics::atomic<Integral> volatile atomic_type;
312             atomic_type a[8];
313             for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
314                 test_atomic_integral_<atomic_type, Integral>( a[i] );
315             }
316         }
317
318         template <class AtomicBool>
319         void do_test_atomic_bool(AtomicBool& a)
320         {
321             EXPECT_TRUE( atomics::atomic_is_lock_free( &a ));
322             atomics::atomic_store( &a, false );
323             EXPECT_FALSE( a );
324             EXPECT_FALSE( atomics::atomic_load( &a ));
325
326             EXPECT_FALSE( atomics::atomic_exchange( &a, true ));
327             EXPECT_TRUE( atomics::atomic_load( &a ));
328             EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
329             EXPECT_FALSE( atomics::atomic_load( &a ));
330
331             bool expected = false;
332             EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, true));
333             EXPECT_FALSE( expected );
334             EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, false));
335             EXPECT_TRUE( expected );
336             EXPECT_TRUE( atomics::atomic_load( &a ));
337
338             atomics::atomic_store( &a, false );
339
340             expected = false;
341             EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, true));
342             EXPECT_FALSE( expected );
343             EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, false));
344             EXPECT_TRUE( expected );
345
346             EXPECT_TRUE( atomics::atomic_load( &a ));
347
348             EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
349         }
350
351         template <class AtomicBool>
352         void do_test_atomic_bool( AtomicBool& a, atomics::memory_order order )
353         {
354             const atomics::memory_order oLoad = convert_to_load_order( order );
355             const atomics::memory_order oStore = convert_to_store_order( order );
356             const atomics::memory_order oExchange = convert_to_exchange_order( order );
357
358             EXPECT_TRUE( atomics::atomic_is_lock_free( &a ));
359             atomics::atomic_store_explicit( &a, false, oStore );
360             EXPECT_FALSE( a == false );
361             EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
362
363             EXPECT_FALSE( atomics::atomic_exchange_explicit( &a, true, oExchange ));
364             EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
365             EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
366             EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
367
368             bool expected = false;
369             EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
370             EXPECT_FALSE( expected );
371             EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
372             EXPECT_TRUE( expected );
373             EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
374
375             atomics::atomic_store( &a, false );
376
377             expected = false;
378             EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
379             EXPECT_FALSE( expected );
380             EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
381             EXPECT_TRUE( expected );
382
383             EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
384
385             EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
386         }
387
388         template <typename Atomic, typename Integral>
389         void test_atomic_pointer_for_( Atomic& a, Integral * arr, Integral aSize, atomics::memory_order order )
390         {
391             typedef Integral integral_type;
392             atomics::memory_order oLoad = convert_to_load_order(order);
393             atomics::memory_order oStore = convert_to_store_order(order);
394             integral_type *  p;
395
396             atomics::atomic_store_explicit( &a, arr, oStore );
397             EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
398
399             p = arr;
400             EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
401             EXPECT_EQ( p, arr + 0 );
402             EXPECT_EQ( *p, 1 );
403             EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
404             EXPECT_EQ( p, arr + 5 );
405             EXPECT_EQ( *p, 6 );
406
407             EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
408             EXPECT_EQ( p, arr + 5 );
409             EXPECT_EQ( *p, 6 );
410             EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
411             EXPECT_EQ( p, arr + 3 );
412             EXPECT_EQ( *p, 4 );
413
414             EXPECT_EQ( atomics::atomic_exchange_explicit( &a, arr, order ), arr + 3 );
415             EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), arr );
416             EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
417
418             for ( integral_type i = 1; i < aSize; ++i ) {
419                 integral_type * p = atomics::atomic_load_explicit( &a, oLoad );
420                 EXPECT_EQ( *p, i );
421                 EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, 1, order ), p );
422                 EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i + 1 );
423             }
424
425             for ( integral_type i = aSize; i > 1; --i ) {
426                 integral_type * p = atomics::atomic_load_explicit( &a, oLoad );
427                 EXPECT_EQ( *p, i  );
428                 EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, 1, order ), p );
429                 EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i - 1 );
430             }
431         }
432
433         template <typename Integral, bool Volatile>
434         void test_atomic_pointer_for()
435         {
436             typedef Integral integral_type;
437             typedef typename add_volatile<atomics::atomic< integral_type *>, Volatile>::type    atomic_pointer;
438
439             integral_type   arr[8];
440             const integral_type aSize = sizeof(arr)/sizeof(arr[0]);
441             for ( integral_type i = 0; i < aSize; ++i ) {
442                 arr[static_cast<size_t>(i)] = i + 1;
443             }
444
445             atomic_pointer  a;
446             integral_type *  p;
447
448             atomics::atomic_store( &a, arr );
449             EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
450
451             p = arr;
452             EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 5 ));
453             EXPECT_EQ( p, arr + 0 );
454             EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 3 ));
455             EXPECT_EQ( p, arr + 5 );
456
457             EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 3 ));
458             EXPECT_EQ( p, arr + 5 );
459             EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 5 ));
460             EXPECT_EQ( p, arr + 3 );
461
462             EXPECT_EQ( atomics::atomic_exchange( &a, arr ), arr + 3 );
463             EXPECT_EQ( atomics::atomic_load( &a ), arr );
464             EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
465
466             for ( integral_type i = 1; i < aSize; ++i ) {
467                 integral_type * p = atomics::atomic_load( &a );
468                 EXPECT_EQ( *p, i );
469                 EXPECT_EQ( atomics::atomic_fetch_add( &a, 1 ), p );
470                 EXPECT_EQ( *atomics::atomic_load( &a ), i + 1 );
471             }
472
473             for ( integral_type i = aSize; i > 1; --i ) {
474                 integral_type * p = atomics::atomic_load( &a );
475                 EXPECT_EQ( *p, i );
476                 EXPECT_EQ( atomics::atomic_fetch_sub( &a, 1 ), p );
477                 EXPECT_EQ( *atomics::atomic_load( &a ), i - 1 );
478             }
479
480             test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_relaxed );
481             test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acquire );
482             test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_release );
483             test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acq_rel );
484             test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_seq_cst );
485
486         }
487
488         template <typename Atomic>
489         void do_test_atomic_pointer_void_( Atomic& a, char * arr, char aSize, atomics::memory_order order )
490         {
491             atomics::memory_order oLoad = convert_to_load_order(order);
492             atomics::memory_order oStore = convert_to_store_order(order);
493             char *  p;
494
495             atomics::atomic_store_explicit( &a, (void *) arr, oStore );
496             EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
497
498             p = arr;
499             EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
500             EXPECT_EQ( p, arr + 0 );
501             EXPECT_EQ( *p, 1 );
502             EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
503             EXPECT_EQ( p, arr + 5 );
504             EXPECT_EQ( *p, 6 );
505
506             EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
507             EXPECT_EQ( p, arr + 5 );
508             EXPECT_EQ( *p, 6 );
509             EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
510             EXPECT_EQ( p, arr + 3 );
511             EXPECT_EQ( *p, 4 );
512
513             EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_exchange_explicit( &a, (void *) arr, order )), arr + 3 );
514             EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), arr );
515             EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
516
517             for ( char i = 1; i < aSize; ++i ) {
518                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i );
519                 atomics::atomic_fetch_add_explicit( &a, 1, order );
520                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i + 1 );
521             }
522
523             for ( char i = aSize; i > 1; --i ) {
524                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i );
525                 atomics::atomic_fetch_sub_explicit( &a, 1, order );
526                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i - 1 );
527             }
528         }
529
530         template <bool Volatile>
531         void do_test_atomic_pointer_void()
532         {
533             typedef typename add_volatile<atomics::atomic< void *>, Volatile>::type    atomic_pointer;
534
535             char   arr[8];
536             const char aSize = sizeof(arr)/sizeof(arr[0]);
537             for ( char i = 0; i < aSize; ++i ) {
538                 arr[static_cast<size_t>(i)] = i + 1;
539             }
540
541             atomic_pointer  a;
542             char *  p;
543
544             atomics::atomic_store( &a, (void *) arr );
545             EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
546
547             p = arr;
548             EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 5)));
549             EXPECT_EQ( p, arr + 0 );
550             EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 3)));
551             EXPECT_EQ( p, arr + 5 );
552
553             EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 3)));
554             EXPECT_EQ( p, arr + 5 );
555             EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 5)));
556             EXPECT_EQ( p, arr + 3 );
557
558             EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_exchange( &a, (void *) arr )), arr + 3 );
559             EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_load( &a )), arr );
560             EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
561
562             for ( char i = 1; i < aSize; ++i ) {
563                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i );
564                 atomics::atomic_fetch_add( &a, 1 );
565                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i + 1 );
566             }
567
568             for ( char i = aSize; i > 1; --i ) {
569                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i );
570                 atomics::atomic_fetch_sub( &a, 1 );
571                 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i - 1 );
572             }
573
574             do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_relaxed );
575             do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acquire );
576             do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_release );
577             do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acq_rel );
578             do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_seq_cst );
579         }
580
581     public:
582         void test_atomic_flag()
583         {
584             atomics::atomic_flag flags[8];
585             for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
586                 do_test_atomic_flag( flags[i] );
587         }
588         void test_atomic_flag_volatile()
589         {
590             atomics::atomic_flag volatile flags[8];
591             for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
592                 do_test_atomic_flag( flags[i] );
593         }
594
595         template <typename AtomicBool>
596         void test_atomic_bool_()
597         {
598             AtomicBool a[8];
599             for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
600                 do_test_atomic_bool( a[i] );
601
602                 do_test_atomic_bool( a[i], atomics::memory_order_relaxed );
603                 do_test_atomic_bool( a[i], atomics::memory_order_acquire );
604                 do_test_atomic_bool( a[i], atomics::memory_order_release );
605                 do_test_atomic_bool( a[i], atomics::memory_order_acq_rel );
606                 do_test_atomic_bool( a[i], atomics::memory_order_seq_cst );
607             }
608         }
609
610         void test_atomic_bool()
611         {
612             test_atomic_bool_<atomics::atomic<bool> >();
613         }
614         void test_atomic_bool_volatile()
615         {
616             test_atomic_bool_<atomics::atomic<bool> volatile >();
617         }
618     };
619
620     TEST_F( cxx11_atomic_func, atomic_char )
621     {
622         test_atomic_integral<char>();
623     }
624     TEST_F( cxx11_atomic_func, atomic_char_volatile )
625     {
626         test_atomic_integral_volatile<char>();
627     }
628     TEST_F( cxx11_atomic_func, atomic_unsigned_char )
629     {
630         test_atomic_integral<unsigned char>();
631     }
632     TEST_F( cxx11_atomic_func, atomic_unsigned_char_volatile )
633     {
634         test_atomic_integral_volatile<unsigned char>();
635     }
636     TEST_F( cxx11_atomic_func, atomic_signed_char )
637     {
638         test_atomic_integral<signed char>();
639     }
640     TEST_F( cxx11_atomic_func, atomic_signed_char_volatile )
641     {
642         test_atomic_integral_volatile<signed char>();
643     }
644     TEST_F( cxx11_atomic_func, atomic_short_int )
645     {
646         test_atomic_integral<short int>();
647     }
648     TEST_F( cxx11_atomic_func, atomic_short_int_volatile )
649     {
650         test_atomic_integral_volatile<short int>();
651     }
652     TEST_F( cxx11_atomic_func, atomic_unsigned_short_int )
653     {
654         test_atomic_integral<unsigned short int>();
655     }
656     TEST_F( cxx11_atomic_func, atomic_unsigned_short_int_volatile )
657     {
658         test_atomic_integral_volatile<unsigned short int>();
659     }
660     TEST_F( cxx11_atomic_func, atomic_int )
661     {
662         test_atomic_integral<int>();
663     }
664     TEST_F( cxx11_atomic_func, atomic_int_volatile )
665     {
666         test_atomic_integral_volatile<int>();
667     }
668     TEST_F( cxx11_atomic_func, atomic_unsigned_int )
669     {
670         test_atomic_integral<unsigned int>();
671     }
672     TEST_F( cxx11_atomic_func, atomic_unsigned_int_volatile )
673     {
674         test_atomic_integral_volatile<unsigned int>();
675     }
676     TEST_F( cxx11_atomic_func, atomic_long )
677     {
678         test_atomic_integral<long>();
679     }
680     TEST_F( cxx11_atomic_func, atomic_long_volatile )
681     {
682         test_atomic_integral_volatile<long>();
683     }
684     TEST_F( cxx11_atomic_func, atomic_unsigned_long )
685     {
686         test_atomic_integral<unsigned long>();
687     }
688     TEST_F( cxx11_atomic_func, atomic_unsigned_long_volatile )
689     {
690         test_atomic_integral_volatile<unsigned long>();
691     }
692     TEST_F( cxx11_atomic_func, atomic_long_long )
693     {
694         test_atomic_integral<long long>();
695     }
696     TEST_F( cxx11_atomic_func, atomic_long_long_volatile )
697     {
698         test_atomic_integral_volatile<long long>();
699     }
700     TEST_F( cxx11_atomic_func, atomic_unsigned_long_long )
701     {
702         test_atomic_integral<unsigned long long>();
703     }
704     TEST_F( cxx11_atomic_func, atomic_unsigned_long_long_volatile )
705     {
706         test_atomic_integral_volatile<unsigned long long>();
707     }
708
709 #if !( CDS_COMPILER == CDS_COMPILER_CLANG && CDS_COMPILER_VERSION < 40000 )
710     //clang error with atomic<void*> fetch_add/fetch_sub
711     TEST_F( cxx11_atomic_func, atomic_pointer_void )
712     {
713         do_test_atomic_pointer_void<false>();
714     }
715     TEST_F( cxx11_atomic_func, atomic_pointer_void_volatile )
716     {
717         do_test_atomic_pointer_void<true>();
718     }
719 #endif
720
721     TEST_F( cxx11_atomic_func, atomic_pointer_char )
722     {
723         test_atomic_pointer_for<char, false>();
724     }
725     TEST_F( cxx11_atomic_func, atomic_pointer_char_volatile )
726     {
727         test_atomic_pointer_for<char, true>();
728     }
729     TEST_F( cxx11_atomic_func, atomic_pointer_short )
730     {
731         test_atomic_pointer_for<short, false>();
732     }
733     TEST_F( cxx11_atomic_func, atomic_pointer_short_volatile )
734     {
735         test_atomic_pointer_for<short, true>();
736     }
737     TEST_F( cxx11_atomic_func, atomic_pointer_int )
738     {
739         test_atomic_pointer_for<int, false>();
740     }
741     TEST_F( cxx11_atomic_func, atomic_pointer_int_volatile )
742     {
743         test_atomic_pointer_for<int, true>();
744     }
745     TEST_F( cxx11_atomic_func, atomic_pointer_long )
746     {
747         test_atomic_pointer_for<long, false>();
748     }
749     TEST_F( cxx11_atomic_func, atomic_pointer_long_volatile )
750     {
751         test_atomic_pointer_for<long, true>();
752     }
753     TEST_F( cxx11_atomic_func, atomic_pointer_long_long )
754     {
755         test_atomic_pointer_for<long long, false>();
756     }
757     TEST_F( cxx11_atomic_func, atomic_pointer_long_long_volatile )
758     {
759         test_atomic_pointer_for<long long, true>();
760     }
761
762     TEST_F( cxx11_atomic_func, test_atomic_fence )
763     {
764         atomics::atomic_thread_fence(atomics::memory_order_relaxed );
765         atomics::atomic_thread_fence(atomics::memory_order_acquire );
766         atomics::atomic_thread_fence(atomics::memory_order_release );
767         atomics::atomic_thread_fence(atomics::memory_order_acq_rel );
768         atomics::atomic_thread_fence(atomics::memory_order_seq_cst );
769
770         atomics::atomic_signal_fence(atomics::memory_order_relaxed );
771         atomics::atomic_signal_fence(atomics::memory_order_acquire );
772         atomics::atomic_signal_fence(atomics::memory_order_release );
773         atomics::atomic_signal_fence(atomics::memory_order_acq_rel );
774         atomics::atomic_signal_fence(atomics::memory_order_seq_cst );
775     }
776 }   // namespace
777
778
779 #endif // #ifndef CDS_USE_BOOST_ATOMIC