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/fp_ops_generic.hpp 10 * 11 * This header contains generic implementation of the floating point atomic operations. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_FP_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/bitwise_fp_cast.hpp> 21 #include <boost/atomic/detail/storage_traits.hpp> 22 #include <boost/atomic/detail/fp_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 floating point operations 34 template< typename Base, typename Value, std::size_t Size > 35 struct fp_operations_generic : 36 public Base 37 { 38 typedef Base base_type; 39 typedef typename base_type::storage_type storage_type; 40 typedef Value value_type; 41 fetch_addboost::atomics::detail::fp_operations_generic42 static BOOST_FORCEINLINE value_type fetch_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT 43 { 44 storage_type old_storage, new_storage; 45 value_type old_val, new_val; 46 atomics::detail::non_atomic_load(storage, old_storage); 47 do 48 { 49 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); 50 new_val = old_val + v; 51 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); 52 } 53 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); 54 return old_val; 55 } 56 fetch_subboost::atomics::detail::fp_operations_generic57 static BOOST_FORCEINLINE value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT 58 { 59 storage_type old_storage, new_storage; 60 value_type old_val, new_val; 61 atomics::detail::non_atomic_load(storage, old_storage); 62 do 63 { 64 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); 65 new_val = old_val - v; 66 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); 67 } 68 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); 69 return old_val; 70 } 71 }; 72 73 // Default fp_operations template definition will be used unless specialized for a specific platform 74 template< typename Base, typename Value, std::size_t Size > 75 struct fp_operations< Base, Value, Size, true > : 76 public fp_operations_generic< Base, Value, Size > 77 { 78 }; 79 80 } // namespace detail 81 } // namespace atomics 82 } // namespace boost 83 84 #include <boost/atomic/detail/footer.hpp> 85 86 #endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ 87