]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/thread/pthread/once_atomic.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / thread / pthread / once_atomic.hpp
1 #ifndef BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP
2 #define BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP
3
4 // once.hpp
5 //
6 // (C) Copyright 2013 Andrey Semashev
7 // (C) Copyright 2013 Vicente J. Botet Escriba
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12
13 #include <boost/thread/detail/config.hpp>
14
15 #include <boost/cstdint.hpp>
16 #include <boost/thread/detail/move.hpp>
17 #include <boost/thread/detail/invoke.hpp>
18 #include <boost/core/no_exceptions_support.hpp>
19 #include <boost/bind/bind.hpp>
20 #include <boost/atomic.hpp>
21
22 #include <boost/config/abi_prefix.hpp>
23
24 namespace boost
25 {
26
27 struct once_flag;
28
29 namespace thread_detail
30 {
31
32 #if BOOST_ATOMIC_INT_LOCK_FREE == 2
33 typedef unsigned int atomic_int_type;
34 #elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2
35 typedef unsigned short atomic_int_type;
36 #elif BOOST_ATOMIC_CHAR_LOCK_FREE == 2
37 typedef unsigned char atomic_int_type;
38 #elif BOOST_ATOMIC_LONG_LOCK_FREE == 2
39 typedef unsigned long atomic_int_type;
40 #elif defined(BOOST_HAS_LONG_LONG) && BOOST_ATOMIC_LLONG_LOCK_FREE == 2
41 typedef ulong_long_type atomic_int_type;
42 #else
43 // All tested integer types are not atomic, the spinlock pool will be used
44 typedef unsigned int atomic_int_type;
45 #endif
46
47 typedef boost::atomic<atomic_int_type> atomic_type;
48
49 BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT;
50 BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT;
51 BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT;
52 inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT;
53 }
54
55 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
56
57 struct once_flag
58 {
59 BOOST_THREAD_NO_COPYABLE(once_flag)
60 BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : storage(0)
61 {
62 }
63
64 private:
65 thread_detail::atomic_type storage;
66
67 friend BOOST_THREAD_DECL bool thread_detail::enter_once_region(once_flag& flag) BOOST_NOEXCEPT;
68 friend BOOST_THREAD_DECL void thread_detail::commit_once_region(once_flag& flag) BOOST_NOEXCEPT;
69 friend BOOST_THREAD_DECL void thread_detail::rollback_once_region(once_flag& flag) BOOST_NOEXCEPT;
70 friend thread_detail::atomic_type& thread_detail::get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT;
71 };
72
73 #define BOOST_ONCE_INIT boost::once_flag()
74
75 namespace thread_detail
76 {
77 inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT
78 {
79 //return reinterpret_cast< atomic_type& >(flag.storage);
80 return flag.storage;
81 }
82 }
83
84 #else // BOOST_THREAD_PROVIDES_ONCE_CXX11
85 struct once_flag
86 {
87 // The thread_detail::atomic_int_type storage is marked
88 // with this attribute in order to let the compiler know that it will alias this member
89 // and silence compilation warnings.
90 BOOST_THREAD_ATTRIBUTE_MAY_ALIAS thread_detail::atomic_int_type storage;
91 };
92
93 #define BOOST_ONCE_INIT {0}
94
95 namespace thread_detail
96 {
97 inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT
98 {
99 return reinterpret_cast< atomic_type& >(flag.storage);
100 }
101
102 }
103
104 #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
105
106 #if defined BOOST_THREAD_PROVIDES_INVOKE
107 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
108 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
109 #elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
110 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
111 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
112 #else
113 #define BOOST_THREAD_INVOKE_RET_VOID boost::bind
114 #define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
115 #endif
116
117
118 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
119
120 template<typename Function, class ...ArgTypes>
121 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
122 {
123 if (thread_detail::enter_once_region(flag))
124 {
125 BOOST_TRY
126 {
127 BOOST_THREAD_INVOKE_RET_VOID(
128 thread_detail::decay_copy(boost::forward<Function>(f)),
129 thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
130 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
131 }
132 BOOST_CATCH (...)
133 {
134 thread_detail::rollback_once_region(flag);
135 BOOST_RETHROW
136 }
137 BOOST_CATCH_END
138 thread_detail::commit_once_region(flag);
139 }
140 }
141 #else
142 template<typename Function>
143 inline void call_once(once_flag& flag, Function f)
144 {
145 if (thread_detail::enter_once_region(flag))
146 {
147 BOOST_TRY
148 {
149 f();
150 }
151 BOOST_CATCH (...)
152 {
153 thread_detail::rollback_once_region(flag);
154 BOOST_RETHROW
155 }
156 BOOST_CATCH_END
157 thread_detail::commit_once_region(flag);
158 }
159 }
160
161 template<typename Function, typename T1>
162 inline void call_once(once_flag& flag, Function f, T1 p1)
163 {
164 if (thread_detail::enter_once_region(flag))
165 {
166 BOOST_TRY
167 {
168 BOOST_THREAD_INVOKE_RET_VOID(f, p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
169 }
170 BOOST_CATCH (...)
171 {
172 thread_detail::rollback_once_region(flag);
173 BOOST_RETHROW
174 }
175 BOOST_CATCH_END
176 thread_detail::commit_once_region(flag);
177 }
178 }
179
180 template<typename Function, typename T1, typename T2>
181 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2)
182 {
183 if (thread_detail::enter_once_region(flag))
184 {
185 BOOST_TRY
186 {
187 BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
188 }
189 BOOST_CATCH (...)
190 {
191 thread_detail::rollback_once_region(flag);
192 BOOST_RETHROW
193 }
194 BOOST_CATCH_END
195 thread_detail::commit_once_region(flag);
196 }
197 }
198
199 template<typename Function, typename T1, typename T2, typename T3>
200 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3)
201 {
202 if (thread_detail::enter_once_region(flag))
203 {
204 BOOST_TRY
205 {
206 BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
207 }
208 BOOST_CATCH (...)
209 {
210 thread_detail::rollback_once_region(flag);
211 BOOST_RETHROW
212 }
213 BOOST_CATCH_END
214 thread_detail::commit_once_region(flag);
215 }
216 }
217 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
218 template<typename Function>
219 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
220 {
221 if (thread_detail::enter_once_region(flag))
222 {
223 BOOST_TRY
224 {
225 f();
226 }
227 BOOST_CATCH (...)
228 {
229 thread_detail::rollback_once_region(flag);
230 BOOST_RETHROW
231 }
232 BOOST_CATCH_END
233 thread_detail::commit_once_region(flag);
234 }
235 }
236
237 template<typename Function, typename T1>
238 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
239 {
240 if (thread_detail::enter_once_region(flag))
241 {
242 BOOST_TRY
243 {
244 BOOST_THREAD_INVOKE_RET_VOID(
245 thread_detail::decay_copy(boost::forward<Function>(f)),
246 thread_detail::decay_copy(boost::forward<T1>(p1))
247 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
248 }
249 BOOST_CATCH (...)
250 {
251 thread_detail::rollback_once_region(flag);
252 BOOST_RETHROW
253 }
254 BOOST_CATCH_END
255 thread_detail::commit_once_region(flag);
256 }
257 }
258 template<typename Function, typename T1, typename T2>
259 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
260 {
261 if (thread_detail::enter_once_region(flag))
262 {
263 BOOST_TRY
264 {
265 BOOST_THREAD_INVOKE_RET_VOID(
266 thread_detail::decay_copy(boost::forward<Function>(f)),
267 thread_detail::decay_copy(boost::forward<T1>(p1)),
268 thread_detail::decay_copy(boost::forward<T1>(p2))
269 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
270 }
271 BOOST_CATCH (...)
272 {
273 thread_detail::rollback_once_region(flag);
274 BOOST_RETHROW
275 }
276 BOOST_CATCH_END
277 thread_detail::commit_once_region(flag);
278 }
279 }
280 template<typename Function, typename T1, typename T2, typename T3>
281 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
282 {
283 if (thread_detail::enter_once_region(flag))
284 {
285 BOOST_TRY
286 {
287 BOOST_THREAD_INVOKE_RET_VOID(
288 thread_detail::decay_copy(boost::forward<Function>(f)),
289 thread_detail::decay_copy(boost::forward<T1>(p1)),
290 thread_detail::decay_copy(boost::forward<T1>(p2)),
291 thread_detail::decay_copy(boost::forward<T1>(p3))
292 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
293
294 }
295 BOOST_CATCH (...)
296 {
297 thread_detail::rollback_once_region(flag);
298 BOOST_RETHROW
299 }
300 BOOST_CATCH_END
301 thread_detail::commit_once_region(flag);
302 }
303 }
304
305 #endif // __SUNPRO_CC
306
307 #endif
308 }
309
310 #include <boost/config/abi_suffix.hpp>
311
312 #endif
313