Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:56

0001 /*
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * Copyright (c) 2015 Andrey Semashev
0007  */
0008 /*!
0009  * \file   atomic/detail/extra_ops_generic.hpp
0010  *
0011  * This header contains generic implementation of the extra atomic operations.
0012  */
0013 
0014 #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_
0015 #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_
0016 
0017 #include <cstddef>
0018 #include <boost/memory_order.hpp>
0019 #include <boost/atomic/detail/config.hpp>
0020 #include <boost/atomic/detail/storage_traits.hpp>
0021 #include <boost/atomic/detail/integral_conversions.hpp>
0022 #include <boost/atomic/detail/extra_operations_fwd.hpp>
0023 #include <boost/atomic/detail/header.hpp>
0024 
0025 #ifdef BOOST_HAS_PRAGMA_ONCE
0026 #pragma once
0027 #endif
0028 
0029 namespace boost {
0030 namespace atomics {
0031 namespace detail {
0032 
0033 //! Generic implementation of extra operations
0034 template< typename Base, std::size_t Size, bool Signed, bool = Base::full_cas_based >
0035 struct extra_operations_generic :
0036     public Base
0037 {
0038     typedef Base base_type;
0039     typedef typename base_type::storage_type storage_type;
0040     typedef typename storage_traits< Size >::type emulated_storage_type;
0041 
0042     static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0043     {
0044         storage_type old_val;
0045         atomics::detail::non_atomic_load(storage, old_val);
0046         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)) {}
0047         return old_val;
0048     }
0049 
0050     static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0051     {
0052         storage_type old_val, new_val;
0053         atomics::detail::non_atomic_load(storage, old_val);
0054         do
0055         {
0056             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val));
0057         }
0058         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0059         return new_val;
0060     }
0061 
0062     static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0063     {
0064         return base_type::fetch_add(storage, v, order) + v;
0065     }
0066 
0067     static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0068     {
0069         return base_type::fetch_sub(storage, v, order) - v;
0070     }
0071 
0072     static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0073     {
0074         return base_type::fetch_and(storage, v, order) & v;
0075     }
0076 
0077     static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0078     {
0079         return base_type::fetch_or(storage, v, order) | v;
0080     }
0081 
0082     static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0083     {
0084         return base_type::fetch_xor(storage, v, order) ^ v;
0085     }
0086 
0087     static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0088     {
0089         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);
0090     }
0091 
0092     static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0093     {
0094         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u)));
0095         return base_type::fetch_xor(storage, mask, order) ^ mask;
0096     }
0097 
0098     static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0099     {
0100         base_type::fetch_add(storage, v, order);
0101     }
0102 
0103     static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0104     {
0105         base_type::fetch_sub(storage, v, order);
0106     }
0107 
0108     static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0109     {
0110         fetch_negate(storage, order);
0111     }
0112 
0113     static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0114     {
0115         base_type::fetch_and(storage, v, order);
0116     }
0117 
0118     static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0119     {
0120         base_type::fetch_or(storage, v, order);
0121     }
0122 
0123     static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0124     {
0125         base_type::fetch_xor(storage, v, order);
0126     }
0127 
0128     static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0129     {
0130         fetch_complement(storage, order);
0131     }
0132 
0133     static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0134     {
0135         return !!static_cast< emulated_storage_type >(add(storage, v, order));
0136     }
0137 
0138     static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0139     {
0140         return !!static_cast< emulated_storage_type >(sub(storage, v, order));
0141     }
0142 
0143     static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0144     {
0145         return !!negate(storage, order);
0146     }
0147 
0148     static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0149     {
0150         return !!bitwise_and(storage, v, order);
0151     }
0152 
0153     static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0154     {
0155         return !!bitwise_or(storage, v, order);
0156     }
0157 
0158     static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0159     {
0160         return !!bitwise_xor(storage, v, order);
0161     }
0162 
0163     static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0164     {
0165         return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order));
0166     }
0167 
0168     static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
0169     {
0170         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
0171         storage_type old_val = base_type::fetch_or(storage, mask, order);
0172         return !!(old_val & mask);
0173     }
0174 
0175     static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
0176     {
0177         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
0178         storage_type old_val = base_type::fetch_and(storage, ~mask, order);
0179         return !!(old_val & mask);
0180     }
0181 
0182     static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
0183     {
0184         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
0185         storage_type old_val = base_type::fetch_xor(storage, mask, order);
0186         return !!(old_val & mask);
0187     }
0188 };
0189 
0190 //! Specialization for cases when the platform only natively supports CAS
0191 template< typename Base, std::size_t Size, bool Signed >
0192 struct extra_operations_generic< Base, Size, Signed, true > :
0193     public Base
0194 {
0195     typedef Base base_type;
0196     typedef typename base_type::storage_type storage_type;
0197     typedef typename storage_traits< Size >::type emulated_storage_type;
0198 
0199     static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0200     {
0201         storage_type old_val;
0202         atomics::detail::non_atomic_load(storage, old_val);
0203         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)) {}
0204         return old_val;
0205     }
0206 
0207     static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0208     {
0209         storage_type old_val, new_val;
0210         atomics::detail::non_atomic_load(storage, old_val);
0211         do
0212         {
0213             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val));
0214         }
0215         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0216         return new_val;
0217     }
0218 
0219     static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0220     {
0221         storage_type old_val, new_val;
0222         atomics::detail::non_atomic_load(storage, old_val);
0223         do
0224         {
0225             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v));
0226         }
0227         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0228         return new_val;
0229     }
0230 
0231     static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0232     {
0233         storage_type old_val, new_val;
0234         atomics::detail::non_atomic_load(storage, old_val);
0235         do
0236         {
0237             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v));
0238         }
0239         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0240         return new_val;
0241     }
0242 
0243     static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0244     {
0245         storage_type old_val, new_val;
0246         atomics::detail::non_atomic_load(storage, old_val);
0247         do
0248         {
0249             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val & v));
0250         }
0251         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0252         return new_val;
0253     }
0254 
0255     static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0256     {
0257         storage_type old_val, new_val;
0258         atomics::detail::non_atomic_load(storage, old_val);
0259         do
0260         {
0261             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val | v));
0262         }
0263         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0264         return new_val;
0265     }
0266 
0267     static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0268     {
0269         storage_type old_val, new_val;
0270         atomics::detail::non_atomic_load(storage, old_val);
0271         do
0272         {
0273             new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val ^ v));
0274         }
0275         while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
0276         return new_val;
0277     }
0278 
0279     static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0280     {
0281         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);
0282     }
0283 
0284     static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0285     {
0286         return bitwise_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
0287     }
0288 
0289     static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0290     {
0291         base_type::fetch_add(storage, v, order);
0292     }
0293 
0294     static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0295     {
0296         base_type::fetch_sub(storage, v, order);
0297     }
0298 
0299     static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0300     {
0301         fetch_negate(storage, order);
0302     }
0303 
0304     static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0305     {
0306         base_type::fetch_and(storage, v, order);
0307     }
0308 
0309     static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0310     {
0311         base_type::fetch_or(storage, v, order);
0312     }
0313 
0314     static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0315     {
0316         base_type::fetch_xor(storage, v, order);
0317     }
0318 
0319     static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0320     {
0321         fetch_complement(storage, order);
0322     }
0323 
0324     static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0325     {
0326         return !!static_cast< emulated_storage_type >(add(storage, v, order));
0327     }
0328 
0329     static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0330     {
0331         return !!static_cast< emulated_storage_type >(sub(storage, v, order));
0332     }
0333 
0334     static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0335     {
0336         return !!negate(storage, order);
0337     }
0338 
0339     static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0340     {
0341         return !!bitwise_and(storage, v, order);
0342     }
0343 
0344     static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0345     {
0346         return !!bitwise_or(storage, v, order);
0347     }
0348 
0349     static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0350     {
0351         return !!bitwise_xor(storage, v, order);
0352     }
0353 
0354     static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
0355     {
0356         return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order));
0357     }
0358 
0359     static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
0360     {
0361         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
0362         storage_type old_val = base_type::fetch_or(storage, mask, order);
0363         return !!(old_val & mask);
0364     }
0365 
0366     static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
0367     {
0368         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
0369         storage_type old_val = base_type::fetch_and(storage, ~mask, order);
0370         return !!(old_val & mask);
0371     }
0372 
0373     static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
0374     {
0375         const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
0376         storage_type old_val = base_type::fetch_xor(storage, mask, order);
0377         return !!(old_val & mask);
0378     }
0379 };
0380 
0381 // Default extra_operations template definition will be used unless specialized for a specific platform
0382 template< typename Base, std::size_t Size, bool Signed >
0383 struct extra_operations< Base, Size, Signed, true > :
0384     public extra_operations_generic< Base, Size, Signed >
0385 {
0386 };
0387 
0388 } // namespace detail
0389 } // namespace atomics
0390 } // namespace boost
0391 
0392 #include <boost/atomic/detail/footer.hpp>
0393 
0394 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_