1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <atomic>
11 
12 // template <class T>
13 // struct atomic<T*>
14 // {
15 //     bool is_lock_free() const volatile;
16 //     bool is_lock_free() const;
17 //     void store(T* desr, memory_order m = memory_order_seq_cst) volatile;
18 //     void store(T* desr, memory_order m = memory_order_seq_cst);
19 //     T* load(memory_order m = memory_order_seq_cst) const volatile;
20 //     T* load(memory_order m = memory_order_seq_cst) const;
21 //     operator T*() const volatile;
22 //     operator T*() const;
23 //     T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile;
24 //     T* exchange(T* desr, memory_order m = memory_order_seq_cst);
25 //     bool compare_exchange_weak(T*& expc, T* desr,
26 //                                memory_order s, memory_order f) volatile;
27 //     bool compare_exchange_weak(T*& expc, T* desr,
28 //                                memory_order s, memory_order f);
29 //     bool compare_exchange_strong(T*& expc, T* desr,
30 //                                  memory_order s, memory_order f) volatile;
31 //     bool compare_exchange_strong(T*& expc, T* desr,
32 //                                  memory_order s, memory_order f);
33 //     bool compare_exchange_weak(T*& expc, T* desr,
34 //                                memory_order m = memory_order_seq_cst) volatile;
35 //     bool compare_exchange_weak(T*& expc, T* desr,
36 //                                memory_order m = memory_order_seq_cst);
37 //     bool compare_exchange_strong(T*& expc, T* desr,
38 //                                 memory_order m = memory_order_seq_cst) volatile;
39 //     bool compare_exchange_strong(T*& expc, T* desr,
40 //                                  memory_order m = memory_order_seq_cst);
41 //     T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile;
42 //     T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst);
43 //     T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile;
44 //     T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst);
45 //
46 //     atomic() = default;
47 //     constexpr atomic(T* desr);
48 //     atomic(const atomic&) = delete;
49 //     atomic& operator=(const atomic&) = delete;
50 //     atomic& operator=(const atomic&) volatile = delete;
51 //
52 //     T* operator=(T*) volatile;
53 //     T* operator=(T*);
54 //     T* operator++(int) volatile;
55 //     T* operator++(int);
56 //     T* operator--(int) volatile;
57 //     T* operator--(int);
58 //     T* operator++() volatile;
59 //     T* operator++();
60 //     T* operator--() volatile;
61 //     T* operator--();
62 //     T* operator+=(ptrdiff_t op) volatile;
63 //     T* operator+=(ptrdiff_t op);
64 //     T* operator-=(ptrdiff_t op) volatile;
65 //     T* operator-=(ptrdiff_t op);
66 // };
67 
68 #include <atomic>
69 #include <new>
70 #include <type_traits>
71 #include <cassert>
72 
73 template <class A, class T>
74 void
do_test()75 do_test()
76 {
77     typedef typename std::remove_pointer<T>::type X;
78     A obj(T(0));
79     assert(obj == T(0));
80     std::atomic_init(&obj, T(1));
81     assert(obj == T(1));
82     std::atomic_init(&obj, T(2));
83     assert(obj == T(2));
84     bool b0 = obj.is_lock_free();
85     obj.store(T(0));
86     assert(obj == T(0));
87     obj.store(T(1), std::memory_order_release);
88     assert(obj == T(1));
89     assert(obj.load() == T(1));
90     assert(obj.load(std::memory_order_acquire) == T(1));
91     assert(obj.exchange(T(2)) == T(1));
92     assert(obj == T(2));
93     assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
94     assert(obj == T(3));
95     T x = obj;
96     assert(obj.compare_exchange_weak(x, T(2)) == true);
97     assert(obj == T(2));
98     assert(x == T(3));
99     assert(obj.compare_exchange_weak(x, T(1)) == false);
100     assert(obj == T(2));
101     assert(x == T(2));
102     x = T(2);
103     assert(obj.compare_exchange_strong(x, T(1)) == true);
104     assert(obj == T(1));
105     assert(x == T(2));
106     assert(obj.compare_exchange_strong(x, T(0)) == false);
107     assert(obj == T(1));
108     assert(x == T(1));
109     assert((obj = T(0)) == T(0));
110     assert(obj == T(0));
111     obj = T(2*sizeof(X));
112     assert((obj += std::ptrdiff_t(3)) == T(5*sizeof(X)));
113     assert(obj == T(5*sizeof(X)));
114     assert((obj -= std::ptrdiff_t(3)) == T(2*sizeof(X)));
115     assert(obj == T(2*sizeof(X)));
116 
117     {
118         _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23};
119         A& zero = *new (storage) A();
120         assert(zero == 0);
121         zero.~A();
122     }
123 }
124 
125 template <class A, class T>
test()126 void test()
127 {
128     do_test<A, T>();
129     do_test<volatile A, T>();
130 }
131 
main()132 int main()
133 {
134     test<std::atomic<int*>, int*>();
135 }
136