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) 2011 Helge Bahmann |
7 | * Copyright (c) 2013 Tim Blechmann |
8 | * Copyright (c) 2014, 2020 Andrey Semashev |
9 | */ |
10 | /*! |
11 | * \file atomic/atomic.hpp |
12 | * |
13 | * This header contains definition of \c atomic template. |
14 | */ |
15 | |
16 | #ifndef BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_ |
17 | #define BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_ |
18 | |
19 | #include <cstddef> |
20 | #include <boost/cstdint.hpp> |
21 | #include <boost/memory_order.hpp> |
22 | #include <boost/atomic/capabilities.hpp> |
23 | #include <boost/atomic/detail/config.hpp> |
24 | #include <boost/atomic/detail/classify.hpp> |
25 | #include <boost/atomic/detail/atomic_impl.hpp> |
26 | #include <boost/atomic/detail/type_traits/is_trivially_copyable.hpp> |
27 | #include <boost/atomic/detail/type_traits/is_nothrow_default_constructible.hpp> |
28 | #include <boost/atomic/detail/header.hpp> |
29 | |
30 | #ifdef BOOST_HAS_PRAGMA_ONCE |
31 | #pragma once |
32 | #endif |
33 | |
34 | namespace boost { |
35 | namespace atomics { |
36 | |
37 | //! Atomic object |
38 | template< typename T > |
39 | class atomic : |
40 | public atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type, false > |
41 | { |
42 | private: |
43 | typedef atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type, false > base_type; |
44 | typedef typename base_type::value_arg_type value_arg_type; |
45 | |
46 | public: |
47 | typedef typename base_type::value_type value_type; |
48 | |
49 | static_assert(sizeof(value_type) > 0u, "boost::atomic<T> requires T to be a complete type" ); |
50 | #if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE) |
51 | static_assert(atomics::detail::is_trivially_copyable< value_type >::value, "boost::atomic<T> requires T to be a trivially copyable type" ); |
52 | #endif |
53 | |
54 | public: |
55 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic() BOOST_NOEXCEPT_IF(atomics::detail::is_nothrow_default_constructible< value_type >::value) : base_type() |
56 | { |
57 | } |
58 | |
59 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v) |
60 | { |
61 | } |
62 | |
63 | BOOST_FORCEINLINE value_type operator= (value_arg_type v) BOOST_NOEXCEPT |
64 | { |
65 | this->store(v); |
66 | return v; |
67 | } |
68 | |
69 | BOOST_FORCEINLINE value_type operator= (value_arg_type v) volatile BOOST_NOEXCEPT |
70 | { |
71 | this->store(v); |
72 | return v; |
73 | } |
74 | |
75 | BOOST_FORCEINLINE operator value_type() const volatile BOOST_NOEXCEPT |
76 | { |
77 | return this->load(); |
78 | } |
79 | |
80 | BOOST_DELETED_FUNCTION(atomic(atomic const&)) |
81 | BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&)) |
82 | BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&) volatile) |
83 | }; |
84 | |
85 | typedef atomic< char > atomic_char; |
86 | typedef atomic< unsigned char > atomic_uchar; |
87 | typedef atomic< signed char > atomic_schar; |
88 | typedef atomic< uint8_t > atomic_uint8_t; |
89 | typedef atomic< int8_t > atomic_int8_t; |
90 | typedef atomic< unsigned short > atomic_ushort; |
91 | typedef atomic< short > atomic_short; |
92 | typedef atomic< uint16_t > atomic_uint16_t; |
93 | typedef atomic< int16_t > atomic_int16_t; |
94 | typedef atomic< unsigned int > atomic_uint; |
95 | typedef atomic< int > atomic_int; |
96 | typedef atomic< uint32_t > atomic_uint32_t; |
97 | typedef atomic< int32_t > atomic_int32_t; |
98 | typedef atomic< unsigned long > atomic_ulong; |
99 | typedef atomic< long > atomic_long; |
100 | typedef atomic< uint64_t > atomic_uint64_t; |
101 | typedef atomic< int64_t > atomic_int64_t; |
102 | #ifdef BOOST_HAS_LONG_LONG |
103 | typedef atomic< boost::ulong_long_type > atomic_ullong; |
104 | typedef atomic< boost::long_long_type > atomic_llong; |
105 | #endif |
106 | typedef atomic< void* > atomic_address; |
107 | typedef atomic< bool > atomic_bool; |
108 | typedef atomic< wchar_t > atomic_wchar_t; |
109 | #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811 |
110 | typedef atomic< char8_t > atomic_char8_t; |
111 | #endif |
112 | #if !defined(BOOST_NO_CXX11_CHAR16_T) |
113 | typedef atomic< char16_t > atomic_char16_t; |
114 | #endif |
115 | #if !defined(BOOST_NO_CXX11_CHAR32_T) |
116 | typedef atomic< char32_t > atomic_char32_t; |
117 | #endif |
118 | |
119 | typedef atomic< int_least8_t > atomic_int_least8_t; |
120 | typedef atomic< uint_least8_t > atomic_uint_least8_t; |
121 | typedef atomic< int_least16_t > atomic_int_least16_t; |
122 | typedef atomic< uint_least16_t > atomic_uint_least16_t; |
123 | typedef atomic< int_least32_t > atomic_int_least32_t; |
124 | typedef atomic< uint_least32_t > atomic_uint_least32_t; |
125 | typedef atomic< int_least64_t > atomic_int_least64_t; |
126 | typedef atomic< uint_least64_t > atomic_uint_least64_t; |
127 | typedef atomic< int_fast8_t > atomic_int_fast8_t; |
128 | typedef atomic< uint_fast8_t > atomic_uint_fast8_t; |
129 | typedef atomic< int_fast16_t > atomic_int_fast16_t; |
130 | typedef atomic< uint_fast16_t > atomic_uint_fast16_t; |
131 | typedef atomic< int_fast32_t > atomic_int_fast32_t; |
132 | typedef atomic< uint_fast32_t > atomic_uint_fast32_t; |
133 | typedef atomic< int_fast64_t > atomic_int_fast64_t; |
134 | typedef atomic< uint_fast64_t > atomic_uint_fast64_t; |
135 | typedef atomic< intmax_t > atomic_intmax_t; |
136 | typedef atomic< uintmax_t > atomic_uintmax_t; |
137 | |
138 | #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) |
139 | typedef atomic< float > atomic_float_t; |
140 | typedef atomic< double > atomic_double_t; |
141 | typedef atomic< long double > atomic_long_double_t; |
142 | #endif |
143 | |
144 | typedef atomic< std::size_t > atomic_size_t; |
145 | typedef atomic< std::ptrdiff_t > atomic_ptrdiff_t; |
146 | |
147 | #if defined(BOOST_HAS_INTPTR_T) |
148 | typedef atomic< boost::intptr_t > atomic_intptr_t; |
149 | typedef atomic< boost::uintptr_t > atomic_uintptr_t; |
150 | #endif |
151 | |
152 | // Select the lock-free atomic types that has natively supported waiting/notifying operations. |
153 | // Prefer 32-bit types the most as those have the best performance on current 32 and 64-bit architectures. |
154 | #if BOOST_ATOMIC_INT32_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY == 2 |
155 | typedef atomic< uint32_t > atomic_unsigned_lock_free; |
156 | typedef atomic< int32_t > atomic_signed_lock_free; |
157 | #elif BOOST_ATOMIC_INT64_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY == 2 |
158 | typedef atomic< uint64_t > atomic_unsigned_lock_free; |
159 | typedef atomic< int64_t > atomic_signed_lock_free; |
160 | #elif BOOST_ATOMIC_INT16_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY == 2 |
161 | typedef atomic< uint16_t > atomic_unsigned_lock_free; |
162 | typedef atomic< int16_t > atomic_signed_lock_free; |
163 | #elif BOOST_ATOMIC_INT8_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY == 2 |
164 | typedef atomic< uint8_t > atomic_unsigned_lock_free; |
165 | typedef atomic< int8_t > atomic_signed_lock_free; |
166 | #elif BOOST_ATOMIC_INT32_LOCK_FREE == 2 |
167 | typedef atomic< uint32_t > atomic_unsigned_lock_free; |
168 | typedef atomic< int32_t > atomic_signed_lock_free; |
169 | #elif BOOST_ATOMIC_INT64_LOCK_FREE == 2 |
170 | typedef atomic< uint64_t > atomic_unsigned_lock_free; |
171 | typedef atomic< int64_t > atomic_signed_lock_free; |
172 | #elif BOOST_ATOMIC_INT16_LOCK_FREE == 2 |
173 | typedef atomic< uint16_t > atomic_unsigned_lock_free; |
174 | typedef atomic< int16_t > atomic_signed_lock_free; |
175 | #elif BOOST_ATOMIC_INT8_LOCK_FREE == 2 |
176 | typedef atomic< uint8_t > atomic_unsigned_lock_free; |
177 | typedef atomic< int8_t > atomic_signed_lock_free; |
178 | #else |
179 | #define BOOST_ATOMIC_DETAIL_NO_LOCK_FREE_TYPEDEFS |
180 | #endif |
181 | |
182 | } // namespace atomics |
183 | |
184 | using atomics::atomic; |
185 | |
186 | using atomics::atomic_char; |
187 | using atomics::atomic_uchar; |
188 | using atomics::atomic_schar; |
189 | using atomics::atomic_uint8_t; |
190 | using atomics::atomic_int8_t; |
191 | using atomics::atomic_ushort; |
192 | using atomics::atomic_short; |
193 | using atomics::atomic_uint16_t; |
194 | using atomics::atomic_int16_t; |
195 | using atomics::atomic_uint; |
196 | using atomics::atomic_int; |
197 | using atomics::atomic_uint32_t; |
198 | using atomics::atomic_int32_t; |
199 | using atomics::atomic_ulong; |
200 | using atomics::atomic_long; |
201 | using atomics::atomic_uint64_t; |
202 | using atomics::atomic_int64_t; |
203 | #ifdef BOOST_HAS_LONG_LONG |
204 | using atomics::atomic_ullong; |
205 | using atomics::atomic_llong; |
206 | #endif |
207 | using atomics::atomic_address; |
208 | using atomics::atomic_bool; |
209 | using atomics::atomic_wchar_t; |
210 | #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811 |
211 | using atomics::atomic_char8_t; |
212 | #endif |
213 | #if !defined(BOOST_NO_CXX11_CHAR16_T) |
214 | using atomics::atomic_char16_t; |
215 | #endif |
216 | #if !defined(BOOST_NO_CXX11_CHAR32_T) |
217 | using atomics::atomic_char32_t; |
218 | #endif |
219 | |
220 | using atomics::atomic_int_least8_t; |
221 | using atomics::atomic_uint_least8_t; |
222 | using atomics::atomic_int_least16_t; |
223 | using atomics::atomic_uint_least16_t; |
224 | using atomics::atomic_int_least32_t; |
225 | using atomics::atomic_uint_least32_t; |
226 | using atomics::atomic_int_least64_t; |
227 | using atomics::atomic_uint_least64_t; |
228 | using atomics::atomic_int_fast8_t; |
229 | using atomics::atomic_uint_fast8_t; |
230 | using atomics::atomic_int_fast16_t; |
231 | using atomics::atomic_uint_fast16_t; |
232 | using atomics::atomic_int_fast32_t; |
233 | using atomics::atomic_uint_fast32_t; |
234 | using atomics::atomic_int_fast64_t; |
235 | using atomics::atomic_uint_fast64_t; |
236 | using atomics::atomic_intmax_t; |
237 | using atomics::atomic_uintmax_t; |
238 | |
239 | #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) |
240 | using atomics::atomic_float_t; |
241 | using atomics::atomic_double_t; |
242 | using atomics::atomic_long_double_t; |
243 | #endif |
244 | |
245 | using atomics::atomic_size_t; |
246 | using atomics::atomic_ptrdiff_t; |
247 | |
248 | #if defined(BOOST_HAS_INTPTR_T) |
249 | using atomics::atomic_intptr_t; |
250 | using atomics::atomic_uintptr_t; |
251 | #endif |
252 | |
253 | #if !defined(BOOST_ATOMIC_DETAIL_NO_LOCK_FREE_TYPEDEFS) |
254 | using atomics::atomic_unsigned_lock_free; |
255 | using atomics::atomic_signed_lock_free; |
256 | #endif |
257 | #undef BOOST_ATOMIC_DETAIL_NO_LOCK_FREE_TYPEDEFS |
258 | |
259 | } // namespace boost |
260 | |
261 | #include <boost/atomic/detail/footer.hpp> |
262 | |
263 | #endif // BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_ |
264 | |