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_type.hpp> 22 #include <boost/atomic/detail/fp_operations_fwd.hpp> 23 24 #ifdef BOOST_HAS_PRAGMA_ONCE 25 #pragma once 26 #endif 27 28 namespace boost { 29 namespace atomics { 30 namespace detail { 31 32 //! Generic implementation of floating point operations 33 template< typename Base, typename Value, std::size_t Size > 34 struct generic_fp_operations : 35 public Base 36 { 37 typedef Base base_type; 38 typedef typename base_type::storage_type storage_type; 39 typedef Value value_type; 40 fetch_addboost::atomics::detail::generic_fp_operations41 static BOOST_FORCEINLINE value_type fetch_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT 42 { 43 storage_type old_storage, new_storage; 44 value_type old_val, new_val; 45 atomics::detail::non_atomic_load(storage, old_storage); 46 do 47 { 48 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); 49 new_val = old_val + v; 50 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); 51 } 52 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); 53 return old_val; 54 } 55 fetch_subboost::atomics::detail::generic_fp_operations56 static BOOST_FORCEINLINE value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT 57 { 58 storage_type old_storage, new_storage; 59 value_type old_val, new_val; 60 atomics::detail::non_atomic_load(storage, old_storage); 61 do 62 { 63 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); 64 new_val = old_val - v; 65 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); 66 } 67 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); 68 return old_val; 69 } 70 }; 71 72 // Default fp_operations template definition will be used unless specialized for a specific platform 73 template< typename Base, typename Value, std::size_t Size > 74 struct fp_operations< Base, Value, Size, true > : 75 public generic_fp_operations< Base, Value, Size > 76 { 77 }; 78 79 } // namespace detail 80 } // namespace atomics 81 } // namespace boost 82 83 #endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ 84