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/static_assert.hpp>
19 #include <boost/memory_order.hpp>
20 #include <boost/atomic/detail/config.hpp>
21 #include <boost/atomic/detail/storage_traits.hpp>
22 #include <boost/atomic/detail/extra_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 extra operations
34 template< typename Base, std::size_t Size, bool Signed >
35 struct extra_operations_emulated :
36     public Base
37 {
38     typedef Base base_type;
39     typedef typename base_type::storage_type storage_type;
40     typedef typename base_type::scoped_lock scoped_lock;
41 
fetch_negateboost::atomics::detail::extra_operations_emulated42     static storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
43     {
44         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
45         storage_type& s = const_cast< storage_type& >(storage);
46         scoped_lock lock(&storage);
47         storage_type old_val = s;
48         s = static_cast< storage_type >(-old_val);
49         return old_val;
50     }
51 
negateboost::atomics::detail::extra_operations_emulated52     static storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
53     {
54         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
55         storage_type& s = const_cast< storage_type& >(storage);
56         scoped_lock lock(&storage);
57         storage_type new_val = static_cast< storage_type >(-s);
58         s = new_val;
59         return new_val;
60     }
61 
addboost::atomics::detail::extra_operations_emulated62     static storage_type add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
63     {
64         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
65         storage_type& s = const_cast< storage_type& >(storage);
66         scoped_lock lock(&storage);
67         storage_type new_val = s;
68         new_val += v;
69         s = new_val;
70         return new_val;
71     }
72 
subboost::atomics::detail::extra_operations_emulated73     static storage_type sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
74     {
75         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
76         storage_type& s = const_cast< storage_type& >(storage);
77         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::extra_operations_emulated84     static storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
85     {
86         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
87         storage_type& s = const_cast< storage_type& >(storage);
88         scoped_lock lock(&storage);
89         storage_type new_val = s;
90         new_val &= v;
91         s = new_val;
92         return new_val;
93     }
94 
bitwise_orboost::atomics::detail::extra_operations_emulated95     static storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
96     {
97         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
98         storage_type& s = const_cast< storage_type& >(storage);
99         scoped_lock lock(&storage);
100         storage_type new_val = s;
101         new_val |= v;
102         s = new_val;
103         return new_val;
104     }
105 
bitwise_xorboost::atomics::detail::extra_operations_emulated106     static storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
107     {
108         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
109         storage_type& s = const_cast< storage_type& >(storage);
110         scoped_lock lock(&storage);
111         storage_type new_val = s;
112         new_val ^= v;
113         s = new_val;
114         return new_val;
115     }
116 
fetch_complementboost::atomics::detail::extra_operations_emulated117     static storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
118     {
119         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
120         storage_type& s = const_cast< storage_type& >(storage);
121         scoped_lock lock(&storage);
122         storage_type old_val = s;
123         s = static_cast< storage_type >(~old_val);
124         return old_val;
125     }
126 
bitwise_complementboost::atomics::detail::extra_operations_emulated127     static storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
128     {
129         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
130         storage_type& s = const_cast< storage_type& >(storage);
131         scoped_lock lock(&storage);
132         storage_type new_val = static_cast< storage_type >(~s);
133         s = new_val;
134         return new_val;
135     }
136 
opaque_addboost::atomics::detail::extra_operations_emulated137     static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
138     {
139         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
140         base_type::fetch_add(storage, v, order);
141     }
142 
opaque_subboost::atomics::detail::extra_operations_emulated143     static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
144     {
145         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
146         base_type::fetch_sub(storage, v, order);
147     }
148 
opaque_negateboost::atomics::detail::extra_operations_emulated149     static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
150     {
151         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
152         fetch_negate(storage, order);
153     }
154 
opaque_andboost::atomics::detail::extra_operations_emulated155     static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
156     {
157         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
158         base_type::fetch_and(storage, v, order);
159     }
160 
opaque_orboost::atomics::detail::extra_operations_emulated161     static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
162     {
163         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
164         base_type::fetch_or(storage, v, order);
165     }
166 
opaque_xorboost::atomics::detail::extra_operations_emulated167     static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
168     {
169         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
170         base_type::fetch_xor(storage, v, order);
171     }
172 
opaque_complementboost::atomics::detail::extra_operations_emulated173     static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
174     {
175         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
176         fetch_complement(storage, order);
177     }
178 
add_and_testboost::atomics::detail::extra_operations_emulated179     static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
180     {
181         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
182         return !!add(storage, v, order);
183     }
184 
sub_and_testboost::atomics::detail::extra_operations_emulated185     static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
186     {
187         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
188         return !!sub(storage, v, order);
189     }
190 
negate_and_testboost::atomics::detail::extra_operations_emulated191     static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
192     {
193         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
194         return !!negate(storage, order);
195     }
196 
and_and_testboost::atomics::detail::extra_operations_emulated197     static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
198     {
199         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
200         return !!bitwise_and(storage, v, order);
201     }
202 
or_and_testboost::atomics::detail::extra_operations_emulated203     static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
204     {
205         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
206         return !!bitwise_or(storage, v, order);
207     }
208 
xor_and_testboost::atomics::detail::extra_operations_emulated209     static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
210     {
211         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
212         return !!bitwise_xor(storage, v, order);
213     }
214 
complement_and_testboost::atomics::detail::extra_operations_emulated215     static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
216     {
217         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
218         return !!bitwise_complement(storage, order);
219     }
220 
bit_test_and_setboost::atomics::detail::extra_operations_emulated221     static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
222     {
223         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
224         storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
225         storage_type old_val = base_type::fetch_or(storage, mask, order);
226         return !!(old_val & mask);
227     }
228 
bit_test_and_resetboost::atomics::detail::extra_operations_emulated229     static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
230     {
231         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
232         storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
233         storage_type old_val = base_type::fetch_and(storage, ~mask, order);
234         return !!(old_val & mask);
235     }
236 
bit_test_and_complementboost::atomics::detail::extra_operations_emulated237     static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
238     {
239         BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
240         storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
241         storage_type old_val = base_type::fetch_xor(storage, mask, order);
242         return !!(old_val & mask);
243     }
244 };
245 
246 template< typename Base, std::size_t Size, bool Signed >
247 struct extra_operations< Base, Size, Signed, false > :
248     public extra_operations_emulated< Base, Size, Signed >
249 {
250 };
251 
252 } // namespace detail
253 } // namespace atomics
254 } // namespace boost
255 
256 #include <boost/atomic/detail/footer.hpp>
257 
258 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_
259