]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 <boost/memory_order.hpp> | |
27 | #include <boost/type_traits/make_signed.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/capabilities.hpp> | |
33 | #include <boost/atomic/detail/ops_msvc_common.hpp> | |
34 | #include <boost/atomic/detail/ops_extending_cas_based.hpp> | |
35 | ||
36 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
37 | #pragma once | |
38 | #endif | |
39 | ||
40 | namespace boost { | |
41 | namespace atomics { | |
42 | namespace detail { | |
43 | ||
44 | struct windows_operations_base | |
45 | { | |
46 | static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; | |
47 | ||
48 | static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT | |
49 | { | |
50 | long tmp; | |
51 | BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0); | |
52 | } | |
53 | ||
54 | static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT | |
55 | { | |
56 | BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); | |
57 | } | |
58 | ||
59 | static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT | |
60 | { | |
61 | BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); | |
62 | } | |
63 | }; | |
64 | ||
65 | template< typename T, typename Derived > | |
66 | struct windows_operations : | |
67 | public windows_operations_base | |
68 | { | |
69 | typedef T storage_type; | |
70 | ||
71 | static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
72 | { | |
73 | Derived::exchange(storage, v, order); | |
74 | } | |
75 | ||
76 | static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT | |
77 | { | |
78 | return Derived::fetch_add(const_cast< storage_type volatile& >(storage), (storage_type)0, order); | |
79 | } | |
80 | ||
81 | static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
82 | { | |
83 | typedef typename make_signed< storage_type >::type signed_storage_type; | |
84 | return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); | |
85 | } | |
86 | ||
87 | static BOOST_FORCEINLINE bool compare_exchange_weak( | |
88 | storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT | |
89 | { | |
90 | return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order); | |
91 | } | |
92 | ||
93 | static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
94 | { | |
95 | return !!Derived::exchange(storage, (storage_type)1, order); | |
96 | } | |
97 | ||
98 | static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
99 | { | |
100 | store(storage, (storage_type)0, order); | |
101 | } | |
102 | ||
103 | static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT | |
104 | { | |
105 | return true; | |
106 | } | |
107 | }; | |
108 | ||
109 | template< bool Signed > | |
110 | struct operations< 4u, Signed > : | |
111 | public windows_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > | |
112 | { | |
113 | typedef windows_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > base_type; | |
114 | typedef typename base_type::storage_type storage_type; | |
115 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_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_ |