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_emulated.hpp
10  *
11  * This header contains emulated (lock-based) implementation of the floating point atomic operations.
12  */
13 
14 #ifndef BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
15 #define BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
16 
17 #include <cstddef>
18 #include <boost/static_assert.hpp>
19 #include <boost/memory_order.hpp>
20 #include <boost/atomic/detail/config.hpp>
21 #include <boost/atomic/detail/bitwise_fp_cast.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 //! Emulated implementation of floating point operations
34 template< typename Base, typename Value, std::size_t Size >
35 struct fp_operations_emulated :
36     public Base
37 {
38     typedef Base base_type;
39     typedef typename base_type::storage_type storage_type;
40     typedef Value value_type;
41     typedef typename base_type::scoped_lock scoped_lock;
42 
fetch_addboost::atomics::detail::fp_operations_emulated43     static value_type fetch_add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
44     {
45         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
46         storage_type& s = const_cast< storage_type& >(storage);
47         scoped_lock lock(&storage);
48         value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
49         value_type new_val = old_val + v;
50         s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
51         return old_val;
52     }
53 
fetch_subboost::atomics::detail::fp_operations_emulated54     static value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
55     {
56         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
57         storage_type& s = const_cast< storage_type& >(storage);
58         scoped_lock lock(&storage);
59         value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
60         value_type new_val = old_val - v;
61         s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
62         return old_val;
63     }
64 };
65 
66 template< typename Base, typename Value, std::size_t Size >
67 struct fp_operations< Base, Value, Size, false > :
68     public fp_operations_emulated< Base, Value, Size >
69 {
70 };
71 
72 } // namespace detail
73 } // namespace atomics
74 } // namespace boost
75 
76 #include <boost/atomic/detail/footer.hpp>
77 
78 #endif // BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
79