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) 2015 Andrey Semashev 7 */ 8 /*! 9 * \file atomic/detail/extra_ops_generic.hpp 10 * 11 * This header contains generic implementation of the extra atomic operations. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_ 16 17 #include <cstddef> 18 #include <boost/memory_order.hpp> 19 #include <boost/atomic/detail/config.hpp> 20 #include <boost/atomic/detail/storage_traits.hpp> 21 #include <boost/atomic/detail/integral_conversions.hpp> 22 #include <boost/atomic/detail/extra_operations_fwd.hpp> 23 #include <boost/atomic/detail/header.hpp> 24 25 #ifdef BOOST_HAS_PRAGMA_ONCE 26 #pragma once 27 #endif 28 29 namespace boost { 30 namespace atomics { 31 namespace detail { 32 33 //! Generic implementation of extra operations 34 template< typename Base, std::size_t Size, bool Signed, bool = Base::full_cas_based > 35 struct extra_operations_generic : 36 public Base 37 { 38 typedef Base base_type; 39 typedef typename base_type::storage_type storage_type; 40 typedef typename storage_traits< Size >::type emulated_storage_type; 41 fetch_negateboost::atomics::detail::extra_operations_generic42 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 43 { 44 storage_type old_val; 45 atomics::detail::non_atomic_load(storage, old_val); 46 while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {} 47 return old_val; 48 } 49 negateboost::atomics::detail::extra_operations_generic50 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 51 { 52 storage_type old_val, new_val; 53 atomics::detail::non_atomic_load(storage, old_val); 54 do 55 { 56 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)); 57 } 58 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 59 return new_val; 60 } 61 addboost::atomics::detail::extra_operations_generic62 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 63 { 64 return base_type::fetch_add(storage, v, order) + v; 65 } 66 subboost::atomics::detail::extra_operations_generic67 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 68 { 69 return base_type::fetch_sub(storage, v, order) - v; 70 } 71 bitwise_andboost::atomics::detail::extra_operations_generic72 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 73 { 74 return base_type::fetch_and(storage, v, order) & v; 75 } 76 bitwise_orboost::atomics::detail::extra_operations_generic77 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 78 { 79 return base_type::fetch_or(storage, v, order) | v; 80 } 81 bitwise_xorboost::atomics::detail::extra_operations_generic82 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 83 { 84 return base_type::fetch_xor(storage, v, order) ^ v; 85 } 86 fetch_complementboost::atomics::detail::extra_operations_generic87 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 88 { 89 return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order); 90 } 91 bitwise_complementboost::atomics::detail::extra_operations_generic92 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 93 { 94 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))); 95 return base_type::fetch_xor(storage, mask, order) ^ mask; 96 } 97 opaque_addboost::atomics::detail::extra_operations_generic98 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 99 { 100 base_type::fetch_add(storage, v, order); 101 } 102 opaque_subboost::atomics::detail::extra_operations_generic103 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 104 { 105 base_type::fetch_sub(storage, v, order); 106 } 107 opaque_negateboost::atomics::detail::extra_operations_generic108 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 109 { 110 fetch_negate(storage, order); 111 } 112 opaque_andboost::atomics::detail::extra_operations_generic113 static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 114 { 115 base_type::fetch_and(storage, v, order); 116 } 117 opaque_orboost::atomics::detail::extra_operations_generic118 static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 119 { 120 base_type::fetch_or(storage, v, order); 121 } 122 opaque_xorboost::atomics::detail::extra_operations_generic123 static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 124 { 125 base_type::fetch_xor(storage, v, order); 126 } 127 opaque_complementboost::atomics::detail::extra_operations_generic128 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 129 { 130 fetch_complement(storage, order); 131 } 132 add_and_testboost::atomics::detail::extra_operations_generic133 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 134 { 135 return !!static_cast< emulated_storage_type >(add(storage, v, order)); 136 } 137 sub_and_testboost::atomics::detail::extra_operations_generic138 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 139 { 140 return !!static_cast< emulated_storage_type >(sub(storage, v, order)); 141 } 142 negate_and_testboost::atomics::detail::extra_operations_generic143 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 144 { 145 return !!negate(storage, order); 146 } 147 and_and_testboost::atomics::detail::extra_operations_generic148 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 149 { 150 return !!bitwise_and(storage, v, order); 151 } 152 or_and_testboost::atomics::detail::extra_operations_generic153 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 154 { 155 return !!bitwise_or(storage, v, order); 156 } 157 xor_and_testboost::atomics::detail::extra_operations_generic158 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 159 { 160 return !!bitwise_xor(storage, v, order); 161 } 162 complement_and_testboost::atomics::detail::extra_operations_generic163 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 164 { 165 return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order)); 166 } 167 bit_test_and_setboost::atomics::detail::extra_operations_generic168 static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 169 { 170 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); 171 storage_type old_val = base_type::fetch_or(storage, mask, order); 172 return !!(old_val & mask); 173 } 174 bit_test_and_resetboost::atomics::detail::extra_operations_generic175 static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 176 { 177 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); 178 storage_type old_val = base_type::fetch_and(storage, ~mask, order); 179 return !!(old_val & mask); 180 } 181 bit_test_and_complementboost::atomics::detail::extra_operations_generic182 static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 183 { 184 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); 185 storage_type old_val = base_type::fetch_xor(storage, mask, order); 186 return !!(old_val & mask); 187 } 188 }; 189 190 //! Specialization for cases when the platform only natively supports CAS 191 template< typename Base, std::size_t Size, bool Signed > 192 struct extra_operations_generic< Base, Size, Signed, true > : 193 public Base 194 { 195 typedef Base base_type; 196 typedef typename base_type::storage_type storage_type; 197 typedef typename storage_traits< Size >::type emulated_storage_type; 198 fetch_negateboost::atomics::detail::extra_operations_generic199 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 200 { 201 storage_type old_val; 202 atomics::detail::non_atomic_load(storage, old_val); 203 while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {} 204 return old_val; 205 } 206 negateboost::atomics::detail::extra_operations_generic207 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 208 { 209 storage_type old_val, new_val; 210 atomics::detail::non_atomic_load(storage, old_val); 211 do 212 { 213 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)); 214 } 215 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 216 return new_val; 217 } 218 addboost::atomics::detail::extra_operations_generic219 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 220 { 221 storage_type old_val, new_val; 222 atomics::detail::non_atomic_load(storage, old_val); 223 do 224 { 225 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v)); 226 } 227 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 228 return new_val; 229 } 230 subboost::atomics::detail::extra_operations_generic231 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 232 { 233 storage_type old_val, new_val; 234 atomics::detail::non_atomic_load(storage, old_val); 235 do 236 { 237 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v)); 238 } 239 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 240 return new_val; 241 } 242 bitwise_andboost::atomics::detail::extra_operations_generic243 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 244 { 245 storage_type old_val, new_val; 246 atomics::detail::non_atomic_load(storage, old_val); 247 do 248 { 249 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val & v)); 250 } 251 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 252 return new_val; 253 } 254 bitwise_orboost::atomics::detail::extra_operations_generic255 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 256 { 257 storage_type old_val, new_val; 258 atomics::detail::non_atomic_load(storage, old_val); 259 do 260 { 261 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val | v)); 262 } 263 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 264 return new_val; 265 } 266 bitwise_xorboost::atomics::detail::extra_operations_generic267 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 268 { 269 storage_type old_val, new_val; 270 atomics::detail::non_atomic_load(storage, old_val); 271 do 272 { 273 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val ^ v)); 274 } 275 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); 276 return new_val; 277 } 278 fetch_complementboost::atomics::detail::extra_operations_generic279 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 280 { 281 return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order); 282 } 283 bitwise_complementboost::atomics::detail::extra_operations_generic284 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 285 { 286 return bitwise_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order); 287 } 288 opaque_addboost::atomics::detail::extra_operations_generic289 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 290 { 291 base_type::fetch_add(storage, v, order); 292 } 293 opaque_subboost::atomics::detail::extra_operations_generic294 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 295 { 296 base_type::fetch_sub(storage, v, order); 297 } 298 opaque_negateboost::atomics::detail::extra_operations_generic299 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 300 { 301 fetch_negate(storage, order); 302 } 303 opaque_andboost::atomics::detail::extra_operations_generic304 static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 305 { 306 base_type::fetch_and(storage, v, order); 307 } 308 opaque_orboost::atomics::detail::extra_operations_generic309 static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 310 { 311 base_type::fetch_or(storage, v, order); 312 } 313 opaque_xorboost::atomics::detail::extra_operations_generic314 static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 315 { 316 base_type::fetch_xor(storage, v, order); 317 } 318 opaque_complementboost::atomics::detail::extra_operations_generic319 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 320 { 321 fetch_complement(storage, order); 322 } 323 add_and_testboost::atomics::detail::extra_operations_generic324 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 325 { 326 return !!static_cast< emulated_storage_type >(add(storage, v, order)); 327 } 328 sub_and_testboost::atomics::detail::extra_operations_generic329 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 330 { 331 return !!static_cast< emulated_storage_type >(sub(storage, v, order)); 332 } 333 negate_and_testboost::atomics::detail::extra_operations_generic334 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 335 { 336 return !!negate(storage, order); 337 } 338 and_and_testboost::atomics::detail::extra_operations_generic339 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 340 { 341 return !!bitwise_and(storage, v, order); 342 } 343 or_and_testboost::atomics::detail::extra_operations_generic344 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 345 { 346 return !!bitwise_or(storage, v, order); 347 } 348 xor_and_testboost::atomics::detail::extra_operations_generic349 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 350 { 351 return !!bitwise_xor(storage, v, order); 352 } 353 complement_and_testboost::atomics::detail::extra_operations_generic354 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 355 { 356 return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order)); 357 } 358 bit_test_and_setboost::atomics::detail::extra_operations_generic359 static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 360 { 361 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); 362 storage_type old_val = base_type::fetch_or(storage, mask, order); 363 return !!(old_val & mask); 364 } 365 bit_test_and_resetboost::atomics::detail::extra_operations_generic366 static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 367 { 368 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); 369 storage_type old_val = base_type::fetch_and(storage, ~mask, order); 370 return !!(old_val & mask); 371 } 372 bit_test_and_complementboost::atomics::detail::extra_operations_generic373 static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 374 { 375 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); 376 storage_type old_val = base_type::fetch_xor(storage, mask, order); 377 return !!(old_val & mask); 378 } 379 }; 380 381 // Default extra_operations template definition will be used unless specialized for a specific platform 382 template< typename Base, std::size_t Size, bool Signed > 383 struct extra_operations< Base, Size, Signed, true > : 384 public extra_operations_generic< Base, Size, Signed > 385 { 386 }; 387 388 } // namespace detail 389 } // namespace atomics 390 } // namespace boost 391 392 #include <boost/atomic/detail/footer.hpp> 393 394 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_ 395