blob: 373d75b09789707d1a93f798fbcf6a11626ae8a9 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===--------------------------- mutex ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_MUTEX
12#define _LIBCPP_MUTEX
13
14/*
15 mutex synopsis
16
17namespace std
18{
19
20class mutex
21{
22public:
Howard Hinnant499c61f2012-07-21 16:13:09 +000023 constexpr mutex() noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024 ~mutex();
25
26 mutex(const mutex&) = delete;
27 mutex& operator=(const mutex&) = delete;
28
29 void lock();
30 bool try_lock();
31 void unlock();
32
33 typedef pthread_mutex_t* native_handle_type;
34 native_handle_type native_handle();
35};
36
37class recursive_mutex
38{
39public:
40 recursive_mutex();
41 ~recursive_mutex();
42
43 recursive_mutex(const recursive_mutex&) = delete;
44 recursive_mutex& operator=(const recursive_mutex&) = delete;
45
46 void lock();
Howard Hinnant499c61f2012-07-21 16:13:09 +000047 bool try_lock() noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000048 void unlock();
49
50 typedef pthread_mutex_t* native_handle_type;
51 native_handle_type native_handle();
52};
53
54class timed_mutex
55{
56public:
57 timed_mutex();
58 ~timed_mutex();
59
60 timed_mutex(const timed_mutex&) = delete;
61 timed_mutex& operator=(const timed_mutex&) = delete;
62
63 void lock();
64 bool try_lock();
65 template <class Rep, class Period>
66 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
67 template <class Clock, class Duration>
68 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
69 void unlock();
70};
71
72class recursive_timed_mutex
73{
74public:
75 recursive_timed_mutex();
76 ~recursive_timed_mutex();
77
78 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
79 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
80
81 void lock();
Howard Hinnant499c61f2012-07-21 16:13:09 +000082 bool try_lock() noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000083 template <class Rep, class Period>
84 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
85 template <class Clock, class Duration>
86 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
87 void unlock();
88};
89
90struct defer_lock_t {};
91struct try_to_lock_t {};
92struct adopt_lock_t {};
93
94constexpr defer_lock_t defer_lock{};
95constexpr try_to_lock_t try_to_lock{};
96constexpr adopt_lock_t adopt_lock{};
97
98template <class Mutex>
99class lock_guard
100{
101public:
102 typedef Mutex mutex_type;
103
104 explicit lock_guard(mutex_type& m);
105 lock_guard(mutex_type& m, adopt_lock_t);
106 ~lock_guard();
107
108 lock_guard(lock_guard const&) = delete;
109 lock_guard& operator=(lock_guard const&) = delete;
110};
111
112template <class Mutex>
113class unique_lock
114{
115public:
116 typedef Mutex mutex_type;
Howard Hinnant499c61f2012-07-21 16:13:09 +0000117 unique_lock() noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000118 explicit unique_lock(mutex_type& m);
Howard Hinnant499c61f2012-07-21 16:13:09 +0000119 unique_lock(mutex_type& m, defer_lock_t) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120 unique_lock(mutex_type& m, try_to_lock_t);
121 unique_lock(mutex_type& m, adopt_lock_t);
122 template <class Clock, class Duration>
123 unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
124 template <class Rep, class Period>
125 unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
126 ~unique_lock();
127
128 unique_lock(unique_lock const&) = delete;
129 unique_lock& operator=(unique_lock const&) = delete;
130
Howard Hinnant499c61f2012-07-21 16:13:09 +0000131 unique_lock(unique_lock&& u) noexcept;
132 unique_lock& operator=(unique_lock&& u) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000133
134 void lock();
135 bool try_lock();
136
137 template <class Rep, class Period>
138 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
139 template <class Clock, class Duration>
140 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
141
142 void unlock();
143
Howard Hinnant499c61f2012-07-21 16:13:09 +0000144 void swap(unique_lock& u) noexcept;
145 mutex_type* release() noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000146
Howard Hinnant499c61f2012-07-21 16:13:09 +0000147 bool owns_lock() const noexcept;
148 explicit operator bool () const noexcept;
149 mutex_type* mutex() const noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000150};
151
152template <class Mutex>
Howard Hinnant499c61f2012-07-21 16:13:09 +0000153 void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154
155template <class L1, class L2, class... L3>
156 int try_lock(L1&, L2&, L3&...);
157template <class L1, class L2, class... L3>
158 void lock(L1&, L2&, L3&...);
159
160struct once_flag
161{
Howard Hinnant499c61f2012-07-21 16:13:09 +0000162 constexpr once_flag() noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000163
164 once_flag(const once_flag&) = delete;
165 once_flag& operator=(const once_flag&) = delete;
166};
167
168template<class Callable, class ...Args>
169 void call_once(once_flag& flag, Callable&& func, Args&&... args);
170
171} // std
172
173*/
174
175#include <__config>
176#include <__mutex_base>
177#include <functional>
Eric Fiselierc6e46692015-07-07 00:27:16 +0000178#include <memory>
Howard Hinnantad935d52011-05-16 19:05:11 +0000179#ifndef _LIBCPP_HAS_NO_VARIADICS
180#include <tuple>
181#endif
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700182#include <sched.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000183
Howard Hinnant66c6f972011-11-29 16:45:27 +0000184#include <__undef_min_max>
185
Howard Hinnant08e17472011-10-17 20:05:10 +0000186#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000187#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000188#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000189
190_LIBCPP_BEGIN_NAMESPACE_STD
191
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +0000192#ifndef _LIBCPP_HAS_NO_THREADS
193
Howard Hinnant83eade62013-03-06 23:30:19 +0000194class _LIBCPP_TYPE_VIS recursive_mutex
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000195{
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700196 pthread_mutex_t __m_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000197
198public:
199 recursive_mutex();
200 ~recursive_mutex();
201
202private:
203 recursive_mutex(const recursive_mutex&); // = delete;
204 recursive_mutex& operator=(const recursive_mutex&); // = delete;
205
206public:
207 void lock();
Howard Hinnant499c61f2012-07-21 16:13:09 +0000208 bool try_lock() _NOEXCEPT;
209 void unlock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000210
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700211 typedef pthread_mutex_t* native_handle_type;
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000212 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000213 native_handle_type native_handle() {return &__m_;}
214};
215
Howard Hinnant83eade62013-03-06 23:30:19 +0000216class _LIBCPP_TYPE_VIS timed_mutex
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000217{
218 mutex __m_;
219 condition_variable __cv_;
220 bool __locked_;
221public:
222 timed_mutex();
223 ~timed_mutex();
224
225private:
226 timed_mutex(const timed_mutex&); // = delete;
227 timed_mutex& operator=(const timed_mutex&); // = delete;
228
229public:
230 void lock();
Howard Hinnant499c61f2012-07-21 16:13:09 +0000231 bool try_lock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000232 template <class _Rep, class _Period>
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000233 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000234 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
Howard Hinnantf8f85212010-11-20 19:16:30 +0000235 {return try_lock_until(chrono::steady_clock::now() + __d);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000236 template <class _Clock, class _Duration>
237 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
Howard Hinnant499c61f2012-07-21 16:13:09 +0000238 void unlock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000239};
240
241template <class _Clock, class _Duration>
242bool
243timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
244{
245 using namespace chrono;
246 unique_lock<mutex> __lk(__m_);
247 bool no_timeout = _Clock::now() < __t;
248 while (no_timeout && __locked_)
249 no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
250 if (!__locked_)
251 {
252 __locked_ = true;
253 return true;
254 }
255 return false;
256}
257
Howard Hinnant83eade62013-03-06 23:30:19 +0000258class _LIBCPP_TYPE_VIS recursive_timed_mutex
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000259{
260 mutex __m_;
261 condition_variable __cv_;
262 size_t __count_;
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700263 pthread_t __id_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264public:
265 recursive_timed_mutex();
266 ~recursive_timed_mutex();
267
268private:
269 recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
270 recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
271
272public:
273 void lock();
Howard Hinnant499c61f2012-07-21 16:13:09 +0000274 bool try_lock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000275 template <class _Rep, class _Period>
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000276 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000277 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
Howard Hinnantf8f85212010-11-20 19:16:30 +0000278 {return try_lock_until(chrono::steady_clock::now() + __d);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000279 template <class _Clock, class _Duration>
280 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
Howard Hinnant499c61f2012-07-21 16:13:09 +0000281 void unlock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000282};
283
284template <class _Clock, class _Duration>
285bool
286recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
287{
288 using namespace chrono;
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700289 pthread_t __id = pthread_self();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000290 unique_lock<mutex> lk(__m_);
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700291 if (pthread_equal(__id, __id_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000292 {
293 if (__count_ == numeric_limits<size_t>::max())
294 return false;
295 ++__count_;
296 return true;
297 }
298 bool no_timeout = _Clock::now() < __t;
299 while (no_timeout && __count_ != 0)
300 no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
301 if (__count_ == 0)
302 {
303 __count_ = 1;
304 __id_ = __id;
305 return true;
306 }
307 return false;
308}
309
310template <class _L0, class _L1>
311int
312try_lock(_L0& __l0, _L1& __l1)
313{
314 unique_lock<_L0> __u0(__l0, try_to_lock);
315 if (__u0.owns_lock())
316 {
317 if (__l1.try_lock())
318 {
319 __u0.release();
320 return -1;
321 }
322 else
323 return 1;
324 }
325 return 0;
326}
327
328#ifndef _LIBCPP_HAS_NO_VARIADICS
329
330template <class _L0, class _L1, class _L2, class... _L3>
331int
332try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
333{
334 int __r = 0;
335 unique_lock<_L0> __u0(__l0, try_to_lock);
336 if (__u0.owns_lock())
337 {
338 __r = try_lock(__l1, __l2, __l3...);
339 if (__r == -1)
340 __u0.release();
341 else
342 ++__r;
343 }
344 return __r;
345}
346
Howard Hinnant324bb032010-08-22 00:02:43 +0000347#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348
349template <class _L0, class _L1>
350void
351lock(_L0& __l0, _L1& __l1)
352{
353 while (true)
354 {
355 {
356 unique_lock<_L0> __u0(__l0);
357 if (__l1.try_lock())
358 {
359 __u0.release();
360 break;
361 }
362 }
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700363 sched_yield();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000364 {
365 unique_lock<_L1> __u1(__l1);
366 if (__l0.try_lock())
367 {
368 __u1.release();
369 break;
370 }
371 }
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700372 sched_yield();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000373 }
374}
375
376#ifndef _LIBCPP_HAS_NO_VARIADICS
377
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000378template <class _L0, class _L1, class _L2, class ..._L3>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000379void
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000380__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000381{
382 while (true)
383 {
384 switch (__i)
385 {
386 case 0:
387 {
388 unique_lock<_L0> __u0(__l0);
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000389 __i = try_lock(__l1, __l2, __l3...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000390 if (__i == -1)
391 {
392 __u0.release();
393 return;
394 }
395 }
396 ++__i;
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700397 sched_yield();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000398 break;
399 case 1:
400 {
401 unique_lock<_L1> __u1(__l1);
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000402 __i = try_lock(__l2, __l3..., __l0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000403 if (__i == -1)
404 {
405 __u1.release();
406 return;
407 }
408 }
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000409 if (__i == sizeof...(_L3) + 1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000410 __i = 0;
411 else
412 __i += 2;
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700413 sched_yield();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000414 break;
415 default:
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000416 __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000417 return;
418 }
419 }
420}
421
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000422template <class _L0, class _L1, class _L2, class ..._L3>
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000423inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000424void
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000425lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000426{
Howard Hinnant6fd4b662011-01-12 22:56:59 +0000427 __lock_first(0, __l0, __l1, __l2, __l3...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000428}
429
Howard Hinnant324bb032010-08-22 00:02:43 +0000430#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000431
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +0000432#endif // !_LIBCPP_HAS_NO_THREADS
433
Marshall Clow05d116e2014-07-29 21:05:31 +0000434struct _LIBCPP_TYPE_VIS_ONLY once_flag;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000435
436#ifndef _LIBCPP_HAS_NO_VARIADICS
437
438template<class _Callable, class... _Args>
Howard Hinnant33be35e2012-09-14 00:39:16 +0000439_LIBCPP_INLINE_VISIBILITY
440void call_once(once_flag&, _Callable&&, _Args&&...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000441
Howard Hinnant324bb032010-08-22 00:02:43 +0000442#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000443
444template<class _Callable>
Howard Hinnant33be35e2012-09-14 00:39:16 +0000445_LIBCPP_INLINE_VISIBILITY
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000446void call_once(once_flag&, _Callable&);
447
448template<class _Callable>
449_LIBCPP_INLINE_VISIBILITY
450void call_once(once_flag&, const _Callable&);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000451
Howard Hinnant324bb032010-08-22 00:02:43 +0000452#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000453
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000454struct _LIBCPP_TYPE_VIS_ONLY once_flag
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000455{
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000456 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000457 _LIBCPP_CONSTEXPR
458 once_flag() _NOEXCEPT : __state_(0) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000459
460private:
461 once_flag(const once_flag&); // = delete;
462 once_flag& operator=(const once_flag&); // = delete;
463
464 unsigned long __state_;
465
466#ifndef _LIBCPP_HAS_NO_VARIADICS
467 template<class _Callable, class... _Args>
468 friend
469 void call_once(once_flag&, _Callable&&, _Args&&...);
Howard Hinnant324bb032010-08-22 00:02:43 +0000470#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000471 template<class _Callable>
472 friend
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000473 void call_once(once_flag&, _Callable&);
474
475 template<class _Callable>
476 friend
477 void call_once(once_flag&, const _Callable&);
Howard Hinnant324bb032010-08-22 00:02:43 +0000478#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000479};
480
Howard Hinnantad935d52011-05-16 19:05:11 +0000481#ifndef _LIBCPP_HAS_NO_VARIADICS
482
Howard Hinnant99968442011-11-29 18:15:50 +0000483template <class _Fp>
Howard Hinnantad935d52011-05-16 19:05:11 +0000484class __call_once_param
485{
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000486 _Fp& __f_;
Howard Hinnantad935d52011-05-16 19:05:11 +0000487public:
Howard Hinnantad935d52011-05-16 19:05:11 +0000488 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000489 explicit __call_once_param(_Fp& __f) : __f_(__f) {}
Howard Hinnantad935d52011-05-16 19:05:11 +0000490
491 _LIBCPP_INLINE_VISIBILITY
492 void operator()()
493 {
Howard Hinnant99968442011-11-29 18:15:50 +0000494 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
Howard Hinnantad935d52011-05-16 19:05:11 +0000495 __execute(_Index());
496 }
497
498private:
499 template <size_t ..._Indices>
500 _LIBCPP_INLINE_VISIBILITY
501 void __execute(__tuple_indices<_Indices...>)
502 {
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000503 __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
Howard Hinnantad935d52011-05-16 19:05:11 +0000504 }
505};
506
507#else
508
Howard Hinnant99968442011-11-29 18:15:50 +0000509template <class _Fp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000510class __call_once_param
511{
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000512 _Fp& __f_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000513public:
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000514 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000515 explicit __call_once_param(_Fp& __f) : __f_(__f) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516
Howard Hinnantb9af2ea2010-09-22 18:02:38 +0000517 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000518 void operator()()
519 {
520 __f_();
521 }
522};
523
Howard Hinnantad935d52011-05-16 19:05:11 +0000524#endif
525
Howard Hinnant99968442011-11-29 18:15:50 +0000526template <class _Fp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000527void
528__call_once_proxy(void* __vp)
529{
Howard Hinnant99968442011-11-29 18:15:50 +0000530 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000531 (*__p)();
532}
533
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000534_LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000535
536#ifndef _LIBCPP_HAS_NO_VARIADICS
537
538template<class _Callable, class... _Args>
539inline _LIBCPP_INLINE_VISIBILITY
540void
541call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
542{
Eric Fiselierc6e46692015-07-07 00:27:16 +0000543 if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000544 {
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000545 typedef tuple<_Callable&&, _Args&&...> _Gp;
546 _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
547 __call_once_param<_Gp> __p(__f);
Howard Hinnant99968442011-11-29 18:15:50 +0000548 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000549 }
550}
551
Howard Hinnant324bb032010-08-22 00:02:43 +0000552#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000553
554template<class _Callable>
555inline _LIBCPP_INLINE_VISIBILITY
556void
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000557call_once(once_flag& __flag, _Callable& __func)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000558{
Eric Fiselierc6e46692015-07-07 00:27:16 +0000559 if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000560 {
561 __call_once_param<_Callable> __p(__func);
562 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
563 }
564}
565
Eric Fiselierbc1e44d2015-06-13 02:23:00 +0000566template<class _Callable>
567inline _LIBCPP_INLINE_VISIBILITY
568void
569call_once(once_flag& __flag, const _Callable& __func)
570{
571 if (__flag.__state_ != ~0ul)
572 {
573 __call_once_param<const _Callable> __p(__func);
574 __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
575 }
576}
577
Howard Hinnant324bb032010-08-22 00:02:43 +0000578#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000579
580_LIBCPP_END_NAMESPACE_STD
581
582#endif // _LIBCPP_MUTEX