1 | #include <boost/config.hpp> |
2 | |
3 | // atomic_sp_test.cpp |
4 | // |
5 | // Copyright 2008, 2017 Peter Dimov |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. |
8 | // See accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt |
10 | |
11 | |
12 | #include <boost/smart_ptr/atomic_shared_ptr.hpp> |
13 | #include <boost/core/lightweight_test.hpp> |
14 | #include <boost/memory_order.hpp> |
15 | |
16 | // |
17 | |
18 | struct X |
19 | { |
20 | }; |
21 | |
22 | #define BOOST_TEST_SP_EQ( p, q ) BOOST_TEST( p == q && !( p < q ) && !( q < p ) ) |
23 | |
24 | int main() |
25 | { |
26 | // default constructor |
27 | |
28 | { |
29 | boost::atomic_shared_ptr<X> apx; |
30 | |
31 | boost::shared_ptr<X> p2 = apx.load(); |
32 | |
33 | BOOST_TEST_EQ( p2.get(), (X*)0 ); |
34 | BOOST_TEST_EQ( p2.use_count(), 0 ); |
35 | } |
36 | |
37 | // shared_ptr constructor |
38 | |
39 | { |
40 | boost::shared_ptr<X> px( new X ); |
41 | boost::atomic_shared_ptr<X> apx( px ); |
42 | |
43 | boost::shared_ptr<X> p2 = apx.load(); |
44 | |
45 | BOOST_TEST_EQ( px, p2 ); |
46 | BOOST_TEST_EQ( px.use_count(), 3 ); |
47 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
48 | } |
49 | |
50 | // shared_ptr assignment |
51 | |
52 | { |
53 | boost::shared_ptr<X> px0( new X ); |
54 | boost::atomic_shared_ptr<X> apx( px0 ); |
55 | |
56 | boost::shared_ptr<X> px( new X ); |
57 | apx = px; |
58 | |
59 | boost::shared_ptr<X> p2 = apx.load(); |
60 | |
61 | BOOST_TEST_EQ( px, p2 ); |
62 | BOOST_TEST_EQ( px.use_count(), 3 ); |
63 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
64 | } |
65 | |
66 | // load, w/ mo |
67 | |
68 | { |
69 | boost::shared_ptr<X> px( new X ); |
70 | boost::atomic_shared_ptr<X> apx( px ); |
71 | |
72 | boost::shared_ptr<X> p2 = apx.load( boost::memory_order_acquire ); |
73 | |
74 | BOOST_TEST_EQ( px, p2 ); |
75 | BOOST_TEST_EQ( px.use_count(), 3 ); |
76 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
77 | } |
78 | |
79 | // operator shared_ptr |
80 | |
81 | { |
82 | boost::shared_ptr<X> px( new X ); |
83 | boost::atomic_shared_ptr<X> apx( px ); |
84 | |
85 | boost::shared_ptr<X> p2 = apx; |
86 | |
87 | BOOST_TEST_EQ( px, p2 ); |
88 | BOOST_TEST_EQ( px.use_count(), 3 ); |
89 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
90 | } |
91 | |
92 | // store |
93 | |
94 | { |
95 | boost::shared_ptr<X> px0( new X ); |
96 | boost::atomic_shared_ptr<X> apx( px0 ); |
97 | |
98 | boost::shared_ptr<X> px( new X ); |
99 | apx.store( r: px ); |
100 | |
101 | boost::shared_ptr<X> p2 = apx.load(); |
102 | |
103 | BOOST_TEST_EQ( px, p2 ); |
104 | BOOST_TEST_EQ( px.use_count(), 3 ); |
105 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
106 | } |
107 | |
108 | // store, w/ mo |
109 | |
110 | { |
111 | boost::shared_ptr<X> px0( new X ); |
112 | boost::atomic_shared_ptr<X> apx( px0 ); |
113 | |
114 | boost::shared_ptr<X> px( new X ); |
115 | apx.store( r: px, boost::memory_order_release ); |
116 | |
117 | boost::shared_ptr<X> p2 = apx.load(); |
118 | |
119 | BOOST_TEST_EQ( px, p2 ); |
120 | BOOST_TEST_EQ( px.use_count(), 3 ); |
121 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
122 | } |
123 | |
124 | // exchange |
125 | |
126 | { |
127 | boost::shared_ptr<X> px0( new X ); |
128 | boost::atomic_shared_ptr<X> apx( px0 ); |
129 | |
130 | boost::shared_ptr<X> px( new X ); |
131 | boost::shared_ptr<X> p1 = apx.exchange( r: px ); |
132 | |
133 | BOOST_TEST_EQ( px0, p1 ); |
134 | BOOST_TEST_EQ( px0.use_count(), 2 ); |
135 | BOOST_TEST_EQ( p1.use_count(), 2 ); |
136 | |
137 | boost::shared_ptr<X> p2 = apx.load(); |
138 | |
139 | BOOST_TEST_EQ( px, p2 ); |
140 | BOOST_TEST_EQ( px.use_count(), 3 ); |
141 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
142 | } |
143 | |
144 | // exchange, w/ mo |
145 | |
146 | { |
147 | boost::shared_ptr<X> px0( new X ); |
148 | boost::atomic_shared_ptr<X> apx( px0 ); |
149 | |
150 | boost::shared_ptr<X> px( new X ); |
151 | boost::shared_ptr<X> p1 = apx.exchange( r: px, boost::memory_order_acq_rel ); |
152 | |
153 | BOOST_TEST_EQ( px0, p1 ); |
154 | BOOST_TEST_EQ( px0.use_count(), 2 ); |
155 | BOOST_TEST_EQ( p1.use_count(), 2 ); |
156 | |
157 | boost::shared_ptr<X> p2 = apx.load(); |
158 | |
159 | BOOST_TEST_EQ( px, p2 ); |
160 | BOOST_TEST_EQ( px.use_count(), 3 ); |
161 | BOOST_TEST_EQ( p2.use_count(), 3 ); |
162 | } |
163 | |
164 | // compare_exchange_weak |
165 | |
166 | { |
167 | boost::shared_ptr<X> px( new X ); |
168 | boost::atomic_shared_ptr<X> apx( px ); |
169 | |
170 | boost::shared_ptr<X> px2( new X ); |
171 | boost::shared_ptr<X> cmp; |
172 | |
173 | bool r = apx.compare_exchange_weak( v&: cmp, w: px2 ); |
174 | BOOST_TEST( !r ); |
175 | BOOST_TEST_SP_EQ( apx.load(), px ); |
176 | BOOST_TEST_SP_EQ( cmp, px ); |
177 | |
178 | r = apx.compare_exchange_weak( v&: cmp, w: px2 ); |
179 | BOOST_TEST( r ); |
180 | BOOST_TEST_SP_EQ( apx.load(), px2 ); |
181 | } |
182 | |
183 | // compare_exchange_weak, w/ mo |
184 | |
185 | { |
186 | boost::shared_ptr<X> px( new X ); |
187 | boost::atomic_shared_ptr<X> apx( px ); |
188 | |
189 | boost::shared_ptr<X> px2( new X ); |
190 | boost::shared_ptr<X> cmp; |
191 | |
192 | bool r = apx.compare_exchange_weak( v&: cmp, w: px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
193 | BOOST_TEST( !r ); |
194 | BOOST_TEST_SP_EQ( apx.load(), px ); |
195 | BOOST_TEST_SP_EQ( cmp, px ); |
196 | |
197 | r = apx.compare_exchange_weak( v&: cmp, w: px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
198 | BOOST_TEST( r ); |
199 | BOOST_TEST_SP_EQ( apx.load(), px2 ); |
200 | } |
201 | |
202 | // compare_exchange_weak, rv |
203 | |
204 | { |
205 | boost::shared_ptr<X> px( new X ); |
206 | boost::atomic_shared_ptr<X> apx( px ); |
207 | |
208 | boost::shared_ptr<X> cmp; |
209 | |
210 | bool r = apx.compare_exchange_weak( v&: cmp, w: boost::shared_ptr<X>() ); |
211 | |
212 | BOOST_TEST( !r ); |
213 | BOOST_TEST_SP_EQ( apx.load(), px ); |
214 | BOOST_TEST_SP_EQ( cmp, px ); |
215 | |
216 | r = apx.compare_exchange_weak( v&: cmp, w: boost::shared_ptr<X>() ); |
217 | |
218 | BOOST_TEST( r ); |
219 | BOOST_TEST( apx.load().get() == 0 ); |
220 | BOOST_TEST( apx.load().use_count() == 0 ); |
221 | } |
222 | |
223 | // compare_exchange_weak, rv, w/ mo |
224 | |
225 | { |
226 | boost::shared_ptr<X> px( new X ); |
227 | boost::atomic_shared_ptr<X> apx( px ); |
228 | |
229 | boost::shared_ptr<X> cmp; |
230 | |
231 | bool r = apx.compare_exchange_weak( v&: cmp, w: boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
232 | |
233 | BOOST_TEST( !r ); |
234 | BOOST_TEST_SP_EQ( apx.load(), px ); |
235 | BOOST_TEST_SP_EQ( cmp, px ); |
236 | |
237 | r = apx.compare_exchange_weak( v&: cmp, w: boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
238 | |
239 | BOOST_TEST( r ); |
240 | BOOST_TEST( apx.load().get() == 0 ); |
241 | BOOST_TEST( apx.load().use_count() == 0 ); |
242 | } |
243 | |
244 | // compare_exchange_strong |
245 | |
246 | { |
247 | boost::shared_ptr<X> px( new X ); |
248 | boost::atomic_shared_ptr<X> apx( px ); |
249 | |
250 | boost::shared_ptr<X> px2( new X ); |
251 | boost::shared_ptr<X> cmp; |
252 | |
253 | bool r = apx.compare_exchange_strong( v&: cmp, w: px2 ); |
254 | BOOST_TEST( !r ); |
255 | BOOST_TEST_SP_EQ( apx.load(), px ); |
256 | BOOST_TEST_SP_EQ( cmp, px ); |
257 | |
258 | r = apx.compare_exchange_strong( v&: cmp, w: px2 ); |
259 | BOOST_TEST( r ); |
260 | BOOST_TEST_SP_EQ( apx.load(), px2 ); |
261 | } |
262 | |
263 | // compare_exchange_strong, w/ mo |
264 | |
265 | { |
266 | boost::shared_ptr<X> px( new X ); |
267 | boost::atomic_shared_ptr<X> apx( px ); |
268 | |
269 | boost::shared_ptr<X> px2( new X ); |
270 | boost::shared_ptr<X> cmp; |
271 | |
272 | bool r = apx.compare_exchange_strong( v&: cmp, w: px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
273 | BOOST_TEST( !r ); |
274 | BOOST_TEST_SP_EQ( apx.load(), px ); |
275 | BOOST_TEST_SP_EQ( cmp, px ); |
276 | |
277 | r = apx.compare_exchange_strong( v&: cmp, w: px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
278 | BOOST_TEST( r ); |
279 | BOOST_TEST_SP_EQ( apx.load(), px2 ); |
280 | } |
281 | |
282 | // compare_exchange_strong, rv |
283 | |
284 | { |
285 | boost::shared_ptr<X> px( new X ); |
286 | boost::atomic_shared_ptr<X> apx( px ); |
287 | |
288 | boost::shared_ptr<X> cmp; |
289 | |
290 | bool r = apx.compare_exchange_strong( v&: cmp, w: boost::shared_ptr<X>() ); |
291 | |
292 | BOOST_TEST( !r ); |
293 | BOOST_TEST_SP_EQ( apx.load(), px ); |
294 | BOOST_TEST_SP_EQ( cmp, px ); |
295 | |
296 | r = apx.compare_exchange_strong( v&: cmp, w: boost::shared_ptr<X>() ); |
297 | |
298 | BOOST_TEST( r ); |
299 | BOOST_TEST( apx.load().get() == 0 ); |
300 | BOOST_TEST( apx.load().use_count() == 0 ); |
301 | } |
302 | |
303 | // compare_exchange_strong, rv, w/ mo |
304 | |
305 | { |
306 | boost::shared_ptr<X> px( new X ); |
307 | boost::atomic_shared_ptr<X> apx( px ); |
308 | |
309 | boost::shared_ptr<X> cmp; |
310 | |
311 | bool r = apx.compare_exchange_strong( v&: cmp, w: boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
312 | |
313 | BOOST_TEST( !r ); |
314 | BOOST_TEST_SP_EQ( apx.load(), px ); |
315 | BOOST_TEST_SP_EQ( cmp, px ); |
316 | |
317 | r = apx.compare_exchange_strong( v&: cmp, w: boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst ); |
318 | |
319 | BOOST_TEST( r ); |
320 | BOOST_TEST( apx.load().get() == 0 ); |
321 | BOOST_TEST( apx.load().use_count() == 0 ); |
322 | } |
323 | |
324 | return boost::report_errors(); |
325 | } |
326 | |