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) 2018 Andrey Semashev 7 */ 8 /*! 9 * \file atomic/detail/extra_ops_emulated.hpp 10 * 11 * This header contains emulated (lock-based) implementation of the extra atomic operations. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_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_type.hpp> 21 #include <boost/atomic/detail/extra_operations_fwd.hpp> 22 #include <boost/atomic/detail/lockpool.hpp> 23 24 #ifdef BOOST_HAS_PRAGMA_ONCE 25 #pragma once 26 #endif 27 28 #if defined(BOOST_MSVC) 29 #pragma warning(push) 30 // unary minus operator applied to unsigned type, result still unsigned 31 #pragma warning(disable: 4146) 32 #endif 33 34 namespace boost { 35 namespace atomics { 36 namespace detail { 37 38 //! Generic implementation of extra operations 39 template< typename Base, std::size_t Size, bool Signed > 40 struct emulated_extra_operations : 41 public Base 42 { 43 typedef Base base_type; 44 typedef typename base_type::storage_type storage_type; 45 fetch_negateboost::atomics::detail::emulated_extra_operations46 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 47 { 48 storage_type& s = const_cast< storage_type& >(storage); 49 lockpool::scoped_lock lock(&storage); 50 storage_type old_val = s; 51 s = static_cast< storage_type >(-old_val); 52 return old_val; 53 } 54 negateboost::atomics::detail::emulated_extra_operations55 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 56 { 57 storage_type& s = const_cast< storage_type& >(storage); 58 lockpool::scoped_lock lock(&storage); 59 storage_type new_val = static_cast< storage_type >(-s); 60 s = new_val; 61 return new_val; 62 } 63 addboost::atomics::detail::emulated_extra_operations64 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 65 { 66 storage_type& s = const_cast< storage_type& >(storage); 67 lockpool::scoped_lock lock(&storage); 68 storage_type new_val = s; 69 new_val += v; 70 s = new_val; 71 return new_val; 72 } 73 subboost::atomics::detail::emulated_extra_operations74 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 75 { 76 storage_type& s = const_cast< storage_type& >(storage); 77 lockpool::scoped_lock lock(&storage); 78 storage_type new_val = s; 79 new_val -= v; 80 s = new_val; 81 return new_val; 82 } 83 bitwise_andboost::atomics::detail::emulated_extra_operations84 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 85 { 86 storage_type& s = const_cast< storage_type& >(storage); 87 lockpool::scoped_lock lock(&storage); 88 storage_type new_val = s; 89 new_val &= v; 90 s = new_val; 91 return new_val; 92 } 93 bitwise_orboost::atomics::detail::emulated_extra_operations94 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 95 { 96 storage_type& s = const_cast< storage_type& >(storage); 97 lockpool::scoped_lock lock(&storage); 98 storage_type new_val = s; 99 new_val |= v; 100 s = new_val; 101 return new_val; 102 } 103 bitwise_xorboost::atomics::detail::emulated_extra_operations104 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 105 { 106 storage_type& s = const_cast< storage_type& >(storage); 107 lockpool::scoped_lock lock(&storage); 108 storage_type new_val = s; 109 new_val ^= v; 110 s = new_val; 111 return new_val; 112 } 113 fetch_complementboost::atomics::detail::emulated_extra_operations114 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 115 { 116 storage_type& s = const_cast< storage_type& >(storage); 117 lockpool::scoped_lock lock(&storage); 118 storage_type old_val = s; 119 s = static_cast< storage_type >(~old_val); 120 return old_val; 121 } 122 bitwise_complementboost::atomics::detail::emulated_extra_operations123 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 124 { 125 storage_type& s = const_cast< storage_type& >(storage); 126 lockpool::scoped_lock lock(&storage); 127 storage_type new_val = static_cast< storage_type >(~s); 128 s = new_val; 129 return new_val; 130 } 131 opaque_addboost::atomics::detail::emulated_extra_operations132 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 133 { 134 Base::fetch_add(storage, v, order); 135 } 136 opaque_subboost::atomics::detail::emulated_extra_operations137 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 138 { 139 Base::fetch_sub(storage, v, order); 140 } 141 opaque_negateboost::atomics::detail::emulated_extra_operations142 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 143 { 144 fetch_negate(storage, order); 145 } 146 opaque_andboost::atomics::detail::emulated_extra_operations147 static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 148 { 149 Base::fetch_and(storage, v, order); 150 } 151 opaque_orboost::atomics::detail::emulated_extra_operations152 static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 153 { 154 Base::fetch_or(storage, v, order); 155 } 156 opaque_xorboost::atomics::detail::emulated_extra_operations157 static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 158 { 159 Base::fetch_xor(storage, v, order); 160 } 161 opaque_complementboost::atomics::detail::emulated_extra_operations162 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 163 { 164 fetch_complement(storage, order); 165 } 166 add_and_testboost::atomics::detail::emulated_extra_operations167 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 168 { 169 return !!add(storage, v, order); 170 } 171 sub_and_testboost::atomics::detail::emulated_extra_operations172 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 173 { 174 return !!sub(storage, v, order); 175 } 176 negate_and_testboost::atomics::detail::emulated_extra_operations177 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 178 { 179 return !!negate(storage, order); 180 } 181 and_and_testboost::atomics::detail::emulated_extra_operations182 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 183 { 184 return !!bitwise_and(storage, v, order); 185 } 186 or_and_testboost::atomics::detail::emulated_extra_operations187 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 188 { 189 return !!bitwise_or(storage, v, order); 190 } 191 xor_and_testboost::atomics::detail::emulated_extra_operations192 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 193 { 194 return !!bitwise_xor(storage, v, order); 195 } 196 complement_and_testboost::atomics::detail::emulated_extra_operations197 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 198 { 199 return !!bitwise_complement(storage, order); 200 } 201 bit_test_and_setboost::atomics::detail::emulated_extra_operations202 static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 203 { 204 storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); 205 storage_type old_val = Base::fetch_or(storage, mask, order); 206 return !!(old_val & mask); 207 } 208 bit_test_and_resetboost::atomics::detail::emulated_extra_operations209 static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 210 { 211 storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); 212 storage_type old_val = Base::fetch_and(storage, ~mask, order); 213 return !!(old_val & mask); 214 } 215 bit_test_and_complementboost::atomics::detail::emulated_extra_operations216 static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 217 { 218 storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); 219 storage_type old_val = Base::fetch_xor(storage, mask, order); 220 return !!(old_val & mask); 221 } 222 }; 223 224 template< typename Base, std::size_t Size, bool Signed > 225 struct extra_operations< Base, Size, Signed, false > : 226 public emulated_extra_operations< Base, Size, Signed > 227 { 228 }; 229 230 } // namespace detail 231 } // namespace atomics 232 } // namespace boost 233 234 #if defined(BOOST_MSVC) 235 #pragma warning(pop) 236 #endif 237 238 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ 239