change support python version
[platform/upstream/boost.git] / boost / atomic / detail / ops_windows.hpp
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) 2009 Helge Bahmann
7  * Copyright (c) 2012 Tim Blechmann
8  * Copyright (c) 2014 Andrey Semashev
9  */
10 /*!
11  * \file   atomic/detail/ops_windows.hpp
12  *
13  * This header contains implementation of the \c operations template.
14  *
15  * This implementation is the most basic version for Windows. It should
16  * work for any non-MSVC-like compilers as long as there are Interlocked WinAPI
17  * functions available. This version is also used for WinCE.
18  *
19  * Notably, this implementation is not as efficient as other
20  * versions based on compiler intrinsics.
21  */
22
23 #ifndef BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
24 #define BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
25
26 #include <cstddef>
27 #include <boost/memory_order.hpp>
28 #include <boost/atomic/detail/config.hpp>
29 #include <boost/atomic/detail/interlocked.hpp>
30 #include <boost/atomic/detail/storage_type.hpp>
31 #include <boost/atomic/detail/operations_fwd.hpp>
32 #include <boost/atomic/detail/type_traits/make_signed.hpp>
33 #include <boost/atomic/capabilities.hpp>
34 #include <boost/atomic/detail/ops_msvc_common.hpp>
35 #include <boost/atomic/detail/ops_extending_cas_based.hpp>
36
37 #ifdef BOOST_HAS_PRAGMA_ONCE
38 #pragma once
39 #endif
40
41 namespace boost {
42 namespace atomics {
43 namespace detail {
44
45 struct windows_operations_base
46 {
47     static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
48     static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
49
50     static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
51     {
52         long tmp;
53         BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
54     }
55
56     static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT
57     {
58         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
59     }
60
61     static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT
62     {
63         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
64     }
65 };
66
67 template< std::size_t Size, bool Signed, typename Derived >
68 struct windows_operations :
69     public windows_operations_base
70 {
71     typedef typename make_storage_type< Size >::type storage_type;
72     typedef typename make_storage_type< Size >::aligned aligned_storage_type;
73
74     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
75     static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
76
77     static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
78     {
79         Derived::exchange(storage, v, order);
80     }
81
82     static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
83     {
84         return Derived::fetch_add(const_cast< storage_type volatile& >(storage), (storage_type)0, order);
85     }
86
87     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
88     {
89         typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type;
90         return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
91     }
92
93     static BOOST_FORCEINLINE bool compare_exchange_weak(
94         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
95     {
96         return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order);
97     }
98
99     static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
100     {
101         return !!Derived::exchange(storage, (storage_type)1, order);
102     }
103
104     static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
105     {
106         store(storage, (storage_type)0, order);
107     }
108 };
109
110 template< bool Signed >
111 struct operations< 4u, Signed > :
112     public windows_operations< 4u, Signed, operations< 4u, Signed > >
113 {
114     typedef windows_operations< 4u, Signed, operations< 4u, Signed > > base_type;
115     typedef typename base_type::storage_type storage_type;
116
117     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
118     {
119         base_type::fence_before(order);
120         v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v));
121         base_type::fence_after(order);
122         return v;
123     }
124
125     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
126     {
127         base_type::fence_before(order);
128         v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v));
129         base_type::fence_after(order);
130         return v;
131     }
132
133     static BOOST_FORCEINLINE bool compare_exchange_strong(
134         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
135     {
136         storage_type previous = expected;
137         base_type::fence_before(success_order);
138         storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous));
139         expected = old_val;
140         // The success and failure fences are the same anyway
141         base_type::fence_after(success_order);
142         return (previous == old_val);
143     }
144
145     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
146     {
147 #if defined(BOOST_ATOMIC_INTERLOCKED_AND)
148         base_type::fence_before(order);
149         v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v));
150         base_type::fence_after(order);
151         return v;
152 #else
153         storage_type res = storage;
154         while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {}
155         return res;
156 #endif
157     }
158
159     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
160     {
161 #if defined(BOOST_ATOMIC_INTERLOCKED_OR)
162         base_type::fence_before(order);
163         v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v));
164         base_type::fence_after(order);
165         return v;
166 #else
167         storage_type res = storage;
168         while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {}
169         return res;
170 #endif
171     }
172
173     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
174     {
175 #if defined(BOOST_ATOMIC_INTERLOCKED_XOR)
176         base_type::fence_before(order);
177         v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v));
178         base_type::fence_after(order);
179         return v;
180 #else
181         storage_type res = storage;
182         while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {}
183         return res;
184 #endif
185     }
186 };
187
188 template< bool Signed >
189 struct operations< 1u, Signed > :
190     public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
191 {
192 };
193
194 template< bool Signed >
195 struct operations< 2u, Signed > :
196     public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
197 {
198 };
199
200 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
201 {
202     BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
203     if (order == memory_order_seq_cst)
204         windows_operations_base::hardware_full_fence();
205     BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
206 }
207
208 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
209 {
210     if (order != memory_order_relaxed)
211         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
212 }
213
214 } // namespace detail
215 } // namespace atomics
216 } // namespace boost
217
218 #endif // BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_