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