1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // <atomic>
10
11 // template <class T>
12 // struct atomic<T*>
13 // {
14 // bool is_lock_free() const volatile;
15 // bool is_lock_free() const;
16 // void store(T* desr, memory_order m = memory_order_seq_cst) volatile;
17 // void store(T* desr, memory_order m = memory_order_seq_cst);
18 // T* load(memory_order m = memory_order_seq_cst) const volatile;
19 // T* load(memory_order m = memory_order_seq_cst) const;
20 // operator T*() const volatile;
21 // operator T*() const;
22 // T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile;
23 // T* exchange(T* desr, memory_order m = memory_order_seq_cst);
24 // bool compare_exchange_weak(T*& expc, T* desr,
25 // memory_order s, memory_order f) volatile;
26 // bool compare_exchange_weak(T*& expc, T* desr,
27 // memory_order s, memory_order f);
28 // bool compare_exchange_strong(T*& expc, T* desr,
29 // memory_order s, memory_order f) volatile;
30 // bool compare_exchange_strong(T*& expc, T* desr,
31 // memory_order s, memory_order f);
32 // bool compare_exchange_weak(T*& expc, T* desr,
33 // memory_order m = memory_order_seq_cst) volatile;
34 // bool compare_exchange_weak(T*& expc, T* desr,
35 // memory_order m = memory_order_seq_cst);
36 // bool compare_exchange_strong(T*& expc, T* desr,
37 // memory_order m = memory_order_seq_cst) volatile;
38 // bool compare_exchange_strong(T*& expc, T* desr,
39 // memory_order m = memory_order_seq_cst);
40 // T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile;
41 // T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst);
42 // T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile;
43 // T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst);
44 //
45 // atomic() = default;
46 // constexpr atomic(T* desr);
47 // atomic(const atomic&) = delete;
48 // atomic& operator=(const atomic&) = delete;
49 // atomic& operator=(const atomic&) volatile = delete;
50 //
51 // T* operator=(T*) volatile;
52 // T* operator=(T*);
53 // T* operator++(int) volatile;
54 // T* operator++(int);
55 // T* operator--(int) volatile;
56 // T* operator--(int);
57 // T* operator++() volatile;
58 // T* operator++();
59 // T* operator--() volatile;
60 // T* operator--();
61 // T* operator+=(ptrdiff_t op) volatile;
62 // T* operator+=(ptrdiff_t op);
63 // T* operator-=(ptrdiff_t op) volatile;
64 // T* operator-=(ptrdiff_t op);
65 // };
66
67 #include <atomic>
68 #include <new>
69 #include <type_traits>
70 #include <cassert>
71
72 #include <cmpxchg_loop.h>
73
74 #include "test_macros.h"
75
76 template <class A, class T>
77 void
do_test()78 do_test()
79 {
80 typedef typename std::remove_pointer<T>::type X;
81 A obj(T(0));
82 assert(obj == T(0));
83 bool b0 = obj.is_lock_free();
84 ((void)b0); // mark as unused
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(cmpxchg_weak_loop(obj, 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 TEST_ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23};
119 A& zero = *new (storage) A();
120 assert(zero == T(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(int,char **)132 int main(int, char**)
133 {
134 test<std::atomic<int*>, int*>();
135
136 return 0;
137 }
138