Line | % of fetches | Source |
---|---|---|
1 | /* | |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * Copyright (c) 2014 Andrey Semashev | |
7 | */ | |
8 | /*! | |
9 | * \file atomic/detail/ops_gcc_atomic.hpp | |
10 | * | |
11 | * This header contains implementation of the \c operations template. | |
12 | */ | |
13 | ||
14 | #ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ | |
15 | #define BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ | |
16 | ||
17 | #include <boost/memory_order.hpp> | |
18 | #include <boost/atomic/detail/config.hpp> | |
19 | #include <boost/atomic/detail/storage_type.hpp> | |
20 | #include <boost/atomic/detail/operations_fwd.hpp> | |
21 | #include <boost/atomic/capabilities.hpp> | |
22 | #if defined(__clang__) && (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)) | |
23 | #include <boost/atomic/detail/ops_gcc_x86_dcas.hpp> | |
24 | #include <boost/atomic/detail/ops_cas_based.hpp> | |
25 | #endif | |
26 | ||
27 | #if __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE ||\ | |
28 | __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE || __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE ||\ | |
29 | __GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE || __GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE ||\ | |
30 | __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE | |
31 | // There are platforms where we need to use larger storage types | |
32 | #include <boost/atomic/detail/int_sizes.hpp> | |
33 | #include <boost/atomic/detail/ops_extending_cas_based.hpp> | |
34 | #endif | |
35 | ||
36 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
37 | #pragma once | |
38 | #endif | |
39 | ||
40 | #if defined(__INTEL_COMPILER) | |
41 | // This is used to suppress warning #32013 described below for Intel Compiler. | |
42 | // In debug builds the compiler does not inline any functions, so basically | |
43 | // every atomic function call results in this warning. I don't know any other | |
44 | // way to selectively disable just this one warning. | |
45 | #pragma system_header | |
46 | #endif | |
47 | ||
48 | namespace boost { | |
49 | namespace atomics { | |
50 | namespace detail { | |
51 | ||
52 | /*! | |
53 | * The function converts \c boost::memory_order values to the compiler-specific constants. | |
54 | * | |
55 | * NOTE: The intention is that the function is optimized away by the compiler, and the | |
56 | * compiler-specific constants are passed to the intrinsics. I know constexpr doesn't | |
57 | * work in this case because the standard atomics interface require memory ordering | |
58 | * constants to be passed as function arguments, at which point they stop being constexpr. | |
59 | * However it is crucial that the compiler sees constants and not runtime values, | |
60 | * because otherwise it just ignores the ordering value and always uses seq_cst. | |
61 | * This is the case with Intel C++ Compiler 14.0.3 (Composer XE 2013 SP1, update 3) and | |
62 | * gcc 4.8.2. Intel Compiler issues a warning in this case: | |
63 | * | |
64 | * warning #32013: Invalid memory order specified. Defaulting to seq_cst memory order. | |
65 | * | |
66 | * while gcc acts silently. | |
67 | * | |
68 | * To mitigate the problem ALL functions, including the atomic<> members must be | |
69 | * declared with BOOST_FORCEINLINE. In this case the compilers are able to see that | |
70 | * all functions are called with constant orderings and call intrinstcts properly. | |
71 | * | |
72 | * Unfortunately, this still doesn't work in debug mode as the compiler doesn't | |
73 | * inline functions even when marked with BOOST_FORCEINLINE. In this case all atomic | |
74 | * operaions will be executed with seq_cst semantics. | |
75 | */ | |
76 | BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT | |
77 | { | |
78 | return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME : | |
79 | (order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE : | |
80 | (order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST))))); | |
81 | } | |
82 | ||
83 | template< typename T > | |
84 | struct gcc_atomic_operations | |
85 | { | |
86 | typedef T storage_type; | |
87 | ||
88 | static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
89 | { | |
90 | __atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
91 | } | |
92 | ||
93 | static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT | |
94 | { | |
95 | return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order)); | |
96 | } | |
97 | ||
98 | static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
99 | { | |
100 | return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
101 | } | |
102 | ||
103 | static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
104 | { | |
105 | return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
106 | } | |
107 | ||
108 | static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
109 | { | |
110 | return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
111 | } | |
112 | ||
113 | static BOOST_FORCEINLINE bool compare_exchange_strong( | |
114 | storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT | |
115 | { | |
116 | return __atomic_compare_exchange_n | |
117 | ( | |
118 | &storage, &expected, desired, false, | |
119 | atomics::detail::convert_memory_order_to_gcc(success_order), | |
120 | atomics::detail::convert_memory_order_to_gcc(failure_order) | |
121 | ); | |
122 | } | |
123 | ||
124 | static BOOST_FORCEINLINE bool compare_exchange_weak( | |
125 | storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT | |
126 | { | |
127 | return __atomic_compare_exchange_n | |
128 | ( | |
129 | &storage, &expected, desired, true, | |
130 | atomics::detail::convert_memory_order_to_gcc(success_order), | |
131 | atomics::detail::convert_memory_order_to_gcc(failure_order) | |
132 | ); | |
133 | } | |
134 | ||
135 | static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
136 | { | |
137 | return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
138 | } | |
139 | ||
140 | static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
141 | { | |
142 | return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
143 | } | |
144 | ||
145 | static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
146 | { | |
147 | return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
148 | } | |
149 | ||
150 | static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
151 | { | |
152 | return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order)); | |
153 | } | |
154 | ||
155 | static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
156 | { | |
157 | __atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order)); | |
158 | } | |
159 | ||
160 | static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT | |
161 | { | |
162 | return __atomic_is_lock_free(sizeof(storage_type), &storage); | |
163 | } | |
164 | }; | |
165 | ||
166 | #if BOOST_ATOMIC_INT128_LOCK_FREE > 0 | |
167 | #if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) | |
168 | ||
169 | // Workaround for clang bug: http://llvm.org/bugs/show_bug.cgi?id=19149 | |
170 | // Clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 | |
171 | template< bool Signed > | |
172 | struct operations< 16u, Signed > : | |
173 | public cas_based_operations< gcc_dcas_x86_64< Signed > > | |
174 | { | |
175 | }; | |
176 | ||
177 | #else | |
178 | ||
179 | template< bool Signed > | |
180 | struct operations< 16u, Signed > : | |
181 | public gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type > | |
182 | { | |
183 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
184 | }; | |
185 | ||
186 | #endif | |
187 | #endif | |
188 | ||
189 | ||
190 | #if BOOST_ATOMIC_INT64_LOCK_FREE > 0 | |
191 | #if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) | |
192 | ||
193 | // Workaround for clang bug http://llvm.org/bugs/show_bug.cgi?id=19355 | |
194 | template< bool Signed > | |
195 | struct operations< 8u, Signed > : | |
196 | public cas_based_operations< gcc_dcas_x86< Signed > > | |
197 | { | |
198 | }; | |
199 | ||
200 | #elif (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
201 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
202 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
203 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
204 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) | |
205 | ||
206 | #define BOOST_ATOMIC_DETAIL_INT64_EXTENDED | |
207 | ||
208 | template< bool Signed > | |
209 | struct operations< 8u, Signed > : | |
210 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 8u, Signed > | |
211 | { | |
212 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
213 | }; | |
214 | ||
215 | #else | |
216 | ||
217 | template< bool Signed > | |
218 | struct operations< 8u, Signed > : | |
219 | public gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type > | |
220 | { | |
221 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
222 | }; | |
223 | ||
224 | #endif | |
225 | #endif | |
226 | ||
227 | #if BOOST_ATOMIC_INT32_LOCK_FREE > 0 | |
228 | #if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
229 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
230 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
231 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
232 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) | |
233 | ||
234 | #define BOOST_ATOMIC_DETAIL_INT32_EXTENDED | |
235 | ||
236 | #if !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
237 | ||
238 | template< bool Signed > | |
239 | struct operations< 4u, Signed > : | |
240 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 4u, Signed > | |
241 | { | |
242 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
243 | }; | |
244 | ||
245 | #else // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
246 | ||
247 | template< bool Signed > | |
248 | struct operations< 4u, Signed > : | |
249 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 4u, Signed > | |
250 | { | |
251 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
252 | }; | |
253 | ||
254 | #endif // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
255 | ||
256 | #else | |
257 | ||
258 | template< bool Signed > | |
259 | struct operations< 4u, Signed > : | |
260 | public gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type > | |
261 | { | |
262 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type; | |
263 | }; | |
264 | ||
265 | #endif | |
266 | #endif | |
267 | ||
268 | #if BOOST_ATOMIC_INT16_LOCK_FREE > 0 | |
269 | #if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
270 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
271 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
272 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
273 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) | |
274 | ||
275 | #define BOOST_ATOMIC_DETAIL_INT16_EXTENDED | |
276 | ||
277 | #if !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED) | |
278 | ||
279 | template< bool Signed > | |
280 | struct operations< 2u, Signed > : | |
281 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 2u, Signed > | |
282 | { | |
283 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type; | |
284 | }; | |
285 | ||
286 | #elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
287 | ||
288 | template< bool Signed > | |
289 | struct operations< 2u, Signed > : | |
290 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 2u, Signed > | |
291 | { | |
292 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
293 | }; | |
294 | ||
295 | #else | |
296 | ||
297 | template< bool Signed > | |
298 | struct operations< 2u, Signed > : | |
299 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 2u, Signed > | |
300 | { | |
301 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
302 | }; | |
303 | ||
304 | #endif | |
305 | ||
306 | #else | |
307 | ||
308 | template< bool Signed > | |
309 | struct operations< 2u, Signed > : | |
310 | public gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type > | |
311 | { | |
312 | typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type; | |
313 | }; | |
314 | ||
315 | #endif | |
316 | #endif | |
317 | ||
318 | #if BOOST_ATOMIC_INT8_LOCK_FREE > 0 | |
319 | #if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
320 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
321 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
322 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
323 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) ||\ | |
324 | (__GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE) ||\ | |
325 | (__GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE) | |
326 | ||
327 | #if !defined(BOOST_ATOMIC_DETAIL_INT16_EXTENDED) | |
328 | ||
329 | template< bool Signed > | |
330 | struct operations< 1u, Signed > : | |
331 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type >, 1u, Signed > | |
332 | { | |
333 | typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type; | |
334 | }; | |
335 | ||
336 | #elif !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED) | |
337 | ||
338 | template< bool Signed > | |
339 | struct operations< 1u, Signed > : | |
340 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 1u, Signed > | |
341 | { | |
342 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type; | |
343 | }; | |
344 | ||
345 | #elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
346 | ||
347 | template< bool Signed > | |
348 | struct operations< 1u, Signed > : | |
349 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 1u, Signed > | |
350 | { | |
351 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
352 | }; | |
353 | ||
354 | #else | |
355 | ||
356 | template< bool Signed > | |
357 | struct operations< 1u, Signed > : | |
358 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 1u, Signed > | |
359 | { | |
360 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
361 | }; | |
362 | ||
363 | #endif | |
364 | ||
365 | #else | |
366 | ||
367 | template< bool Signed > | |
368 | struct operations< 1u, Signed > : | |
369 | public gcc_atomic_operations< typename make_storage_type< 1u, Signed >::type > | |
370 | { | |
371 | typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type; | |
372 | }; | |
373 | ||
374 | #endif | |
375 | #endif | |
376 | ||
377 | #undef BOOST_ATOMIC_DETAIL_INT16_EXTENDED | |
378 | #undef BOOST_ATOMIC_DETAIL_INT32_EXTENDED | |
379 | #undef BOOST_ATOMIC_DETAIL_INT64_EXTENDED | |
380 | ||
381 | BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT | |
382 | { | |
383 | __atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order)); | |
384 | } | |
385 | ||
386 | BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT | |
387 | { | |
388 | __atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order)); | |
389 | } | |
390 | ||
391 | } // namespace detail | |
392 | } // namespace atomics | |
393 | } // namespace boost | |
394 | ||
395 | #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ | |
396 |
Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.