blob: e2a0daa3eab553fab32fcff7218bf9fe71278938 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===--------------------------- mutex ------------------------------------===//
3//
Howard Hinnantc566dc32010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00005//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +000023 constexpr mutex() noexcept;
Howard Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +000047 bool try_lock() noexcept;
Howard Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +000082 bool try_lock() noexcept;
Howard Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +0000117 unique_lock() noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000118 explicit unique_lock(mutex_type& m);
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000119 unique_lock(mutex_type& m, defer_lock_t) noexcept;
Howard Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +0000131 unique_lock(unique_lock&& u) noexcept;
132 unique_lock& operator=(unique_lock&& u) noexcept;
Howard Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +0000144 void swap(unique_lock& u) noexcept;
145 mutex_type* release() noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000146
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000147 bool owns_lock() const noexcept;
148 explicit operator bool () const noexcept;
149 mutex_type* mutex() const noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000150};
151
152template <class Mutex>
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000153 void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
Howard Hinnantc51e1022010-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 Hinnantbd05d6a2012-07-21 16:13:09 +0000162 constexpr once_flag() noexcept;
Howard Hinnantc51e1022010-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>
Howard Hinnant51d62e02011-05-16 19:05:11 +0000178#ifndef _LIBCPP_HAS_NO_VARIADICS
179#include <tuple>
180#endif
Sergey Dmitrouk7dfca3d2014-12-08 14:50:21 +0000181#include <sched.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000182
Howard Hinnantc5a5fbd2011-11-29 16:45:27 +0000183#include <__undef_min_max>
184
Howard Hinnantaaaa52b2011-10-17 20:05:10 +0000185#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000186#pragma GCC system_header
Howard Hinnantaaaa52b2011-10-17 20:05:10 +0000187#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000188
189_LIBCPP_BEGIN_NAMESPACE_STD
190
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000191#ifndef _LIBCPP_HAS_NO_THREADS
192
Howard Hinnant8331b762013-03-06 23:30:19 +0000193class _LIBCPP_TYPE_VIS recursive_mutex
Howard Hinnantc51e1022010-05-11 19:42:16 +0000194{
195 pthread_mutex_t __m_;
196
197public:
198 recursive_mutex();
199 ~recursive_mutex();
200
201private:
202 recursive_mutex(const recursive_mutex&); // = delete;
203 recursive_mutex& operator=(const recursive_mutex&); // = delete;
204
205public:
206 void lock();
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000207 bool try_lock() _NOEXCEPT;
208 void unlock() _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000209
210 typedef pthread_mutex_t* native_handle_type;
Howard Hinnantf5f99992010-09-22 18:02:38 +0000211 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000212 native_handle_type native_handle() {return &__m_;}
213};
214
Howard Hinnant8331b762013-03-06 23:30:19 +0000215class _LIBCPP_TYPE_VIS timed_mutex
Howard Hinnantc51e1022010-05-11 19:42:16 +0000216{
217 mutex __m_;
218 condition_variable __cv_;
219 bool __locked_;
220public:
221 timed_mutex();
222 ~timed_mutex();
223
224private:
225 timed_mutex(const timed_mutex&); // = delete;
226 timed_mutex& operator=(const timed_mutex&); // = delete;
227
228public:
229 void lock();
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000230 bool try_lock() _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000231 template <class _Rep, class _Period>
Howard Hinnantf5f99992010-09-22 18:02:38 +0000232 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
Howard Hinnantc8dbd222010-11-20 19:16:30 +0000234 {return try_lock_until(chrono::steady_clock::now() + __d);}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000235 template <class _Clock, class _Duration>
236 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000237 void unlock() _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000238};
239
240template <class _Clock, class _Duration>
241bool
242timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
243{
244 using namespace chrono;
245 unique_lock<mutex> __lk(__m_);
246 bool no_timeout = _Clock::now() < __t;
247 while (no_timeout && __locked_)
248 no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
249 if (!__locked_)
250 {
251 __locked_ = true;
252 return true;
253 }
254 return false;
255}
256
Howard Hinnant8331b762013-03-06 23:30:19 +0000257class _LIBCPP_TYPE_VIS recursive_timed_mutex
Howard Hinnantc51e1022010-05-11 19:42:16 +0000258{
259 mutex __m_;
260 condition_variable __cv_;
261 size_t __count_;
262 pthread_t __id_;
263public:
264 recursive_timed_mutex();
265 ~recursive_timed_mutex();
266
267private:
268 recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
269 recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
270
271public:
272 void lock();
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000273 bool try_lock() _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000274 template <class _Rep, class _Period>
Howard Hinnantf5f99992010-09-22 18:02:38 +0000275 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
Howard Hinnantc8dbd222010-11-20 19:16:30 +0000277 {return try_lock_until(chrono::steady_clock::now() + __d);}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000278 template <class _Clock, class _Duration>
279 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000280 void unlock() _NOEXCEPT;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281};
282
283template <class _Clock, class _Duration>
284bool
285recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
286{
287 using namespace chrono;
288 pthread_t __id = pthread_self();
289 unique_lock<mutex> lk(__m_);
290 if (pthread_equal(__id, __id_))
291 {
292 if (__count_ == numeric_limits<size_t>::max())
293 return false;
294 ++__count_;
295 return true;
296 }
297 bool no_timeout = _Clock::now() < __t;
298 while (no_timeout && __count_ != 0)
299 no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
300 if (__count_ == 0)
301 {
302 __count_ = 1;
303 __id_ = __id;
304 return true;
305 }
306 return false;
307}
308
309template <class _L0, class _L1>
310int
311try_lock(_L0& __l0, _L1& __l1)
312{
313 unique_lock<_L0> __u0(__l0, try_to_lock);
314 if (__u0.owns_lock())
315 {
316 if (__l1.try_lock())
317 {
318 __u0.release();
319 return -1;
320 }
321 else
322 return 1;
323 }
324 return 0;
325}
326
327#ifndef _LIBCPP_HAS_NO_VARIADICS
328
329template <class _L0, class _L1, class _L2, class... _L3>
330int
331try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
332{
333 int __r = 0;
334 unique_lock<_L0> __u0(__l0, try_to_lock);
335 if (__u0.owns_lock())
336 {
337 __r = try_lock(__l1, __l2, __l3...);
338 if (__r == -1)
339 __u0.release();
340 else
341 ++__r;
342 }
343 return __r;
344}
345
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000346#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000347
348template <class _L0, class _L1>
349void
350lock(_L0& __l0, _L1& __l1)
351{
352 while (true)
353 {
354 {
355 unique_lock<_L0> __u0(__l0);
356 if (__l1.try_lock())
357 {
358 __u0.release();
359 break;
360 }
361 }
362 sched_yield();
363 {
364 unique_lock<_L1> __u1(__l1);
365 if (__l0.try_lock())
366 {
367 __u1.release();
368 break;
369 }
370 }
371 sched_yield();
372 }
373}
374
375#ifndef _LIBCPP_HAS_NO_VARIADICS
376
Howard Hinnantf8485322011-01-12 22:56:59 +0000377template <class _L0, class _L1, class _L2, class ..._L3>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000378void
Howard Hinnantf8485322011-01-12 22:56:59 +0000379__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000380{
381 while (true)
382 {
383 switch (__i)
384 {
385 case 0:
386 {
387 unique_lock<_L0> __u0(__l0);
Howard Hinnantf8485322011-01-12 22:56:59 +0000388 __i = try_lock(__l1, __l2, __l3...);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000389 if (__i == -1)
390 {
391 __u0.release();
392 return;
393 }
394 }
395 ++__i;
396 sched_yield();
397 break;
398 case 1:
399 {
400 unique_lock<_L1> __u1(__l1);
Howard Hinnantf8485322011-01-12 22:56:59 +0000401 __i = try_lock(__l2, __l3..., __l0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000402 if (__i == -1)
403 {
404 __u1.release();
405 return;
406 }
407 }
Howard Hinnantf8485322011-01-12 22:56:59 +0000408 if (__i == sizeof...(_L3) + 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000409 __i = 0;
410 else
411 __i += 2;
412 sched_yield();
413 break;
414 default:
Howard Hinnantf8485322011-01-12 22:56:59 +0000415 __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000416 return;
417 }
418 }
419}
420
Howard Hinnantf8485322011-01-12 22:56:59 +0000421template <class _L0, class _L1, class _L2, class ..._L3>
Howard Hinnantf5f99992010-09-22 18:02:38 +0000422inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000423void
Howard Hinnantf8485322011-01-12 22:56:59 +0000424lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000425{
Howard Hinnantf8485322011-01-12 22:56:59 +0000426 __lock_first(0, __l0, __l1, __l2, __l3...);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000427}
428
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000429#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000430
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000431#endif // !_LIBCPP_HAS_NO_THREADS
432
Marshall Clow7ed42342014-07-29 21:05:31 +0000433struct _LIBCPP_TYPE_VIS_ONLY once_flag;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000434
435#ifndef _LIBCPP_HAS_NO_VARIADICS
436
437template<class _Callable, class... _Args>
Howard Hinnanta54386e2012-09-14 00:39:16 +0000438_LIBCPP_INLINE_VISIBILITY
439void call_once(once_flag&, _Callable&&, _Args&&...);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000440
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000441#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000442
443template<class _Callable>
Howard Hinnanta54386e2012-09-14 00:39:16 +0000444_LIBCPP_INLINE_VISIBILITY
445void call_once(once_flag&, _Callable);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000446
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000447#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000448
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000449struct _LIBCPP_TYPE_VIS_ONLY once_flag
Howard Hinnantc51e1022010-05-11 19:42:16 +0000450{
Howard Hinnantf5f99992010-09-22 18:02:38 +0000451 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000452 _LIBCPP_CONSTEXPR
453 once_flag() _NOEXCEPT : __state_(0) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000454
455private:
456 once_flag(const once_flag&); // = delete;
457 once_flag& operator=(const once_flag&); // = delete;
458
459 unsigned long __state_;
460
461#ifndef _LIBCPP_HAS_NO_VARIADICS
462 template<class _Callable, class... _Args>
463 friend
464 void call_once(once_flag&, _Callable&&, _Args&&...);
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000465#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000466 template<class _Callable>
467 friend
468 void call_once(once_flag&, _Callable);
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000469#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470};
471
Howard Hinnant51d62e02011-05-16 19:05:11 +0000472#ifndef _LIBCPP_HAS_NO_VARIADICS
473
Howard Hinnantc834c512011-11-29 18:15:50 +0000474template <class _Fp>
Howard Hinnant51d62e02011-05-16 19:05:11 +0000475class __call_once_param
476{
Howard Hinnantc834c512011-11-29 18:15:50 +0000477 _Fp __f_;
Howard Hinnant51d62e02011-05-16 19:05:11 +0000478public:
479#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
480 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc834c512011-11-29 18:15:50 +0000481 explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
Howard Hinnant51d62e02011-05-16 19:05:11 +0000482#else
483 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc834c512011-11-29 18:15:50 +0000484 explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
Howard Hinnant51d62e02011-05-16 19:05:11 +0000485#endif
486
487 _LIBCPP_INLINE_VISIBILITY
488 void operator()()
489 {
Howard Hinnantc834c512011-11-29 18:15:50 +0000490 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
Howard Hinnant51d62e02011-05-16 19:05:11 +0000491 __execute(_Index());
492 }
493
494private:
495 template <size_t ..._Indices>
496 _LIBCPP_INLINE_VISIBILITY
497 void __execute(__tuple_indices<_Indices...>)
498 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000499 __invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...);
Howard Hinnant51d62e02011-05-16 19:05:11 +0000500 }
501};
502
503#else
504
Howard Hinnantc834c512011-11-29 18:15:50 +0000505template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000506class __call_once_param
507{
Howard Hinnantc834c512011-11-29 18:15:50 +0000508 _Fp __f_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509public:
Howard Hinnant74279a52010-09-04 23:28:19 +0000510#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantf5f99992010-09-22 18:02:38 +0000511 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc834c512011-11-29 18:15:50 +0000512 explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000513#else
Howard Hinnantf5f99992010-09-22 18:02:38 +0000514 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc834c512011-11-29 18:15:50 +0000515 explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000516#endif
517
Howard Hinnantf5f99992010-09-22 18:02:38 +0000518 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000519 void operator()()
520 {
521 __f_();
522 }
523};
524
Howard Hinnant51d62e02011-05-16 19:05:11 +0000525#endif
526
Howard Hinnantc834c512011-11-29 18:15:50 +0000527template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000528void
529__call_once_proxy(void* __vp)
530{
Howard Hinnantc834c512011-11-29 18:15:50 +0000531 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000532 (*__p)();
533}
534
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000535_LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000536
537#ifndef _LIBCPP_HAS_NO_VARIADICS
538
539template<class _Callable, class... _Args>
540inline _LIBCPP_INLINE_VISIBILITY
541void
542call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
543{
Howard Hinnant28b24882011-12-01 20:21:04 +0000544 if (__flag.__state_ != ~0ul)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000545 {
Howard Hinnantc834c512011-11-29 18:15:50 +0000546 typedef tuple<typename decay<_Callable>::type, typename decay<_Args>::type...> _Gp;
547 __call_once_param<_Gp> __p(_Gp(__decay_copy(_VSTD::forward<_Callable>(__func)),
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000548 __decay_copy(_VSTD::forward<_Args>(__args))...));
Howard Hinnantc834c512011-11-29 18:15:50 +0000549 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000550 }
551}
552
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000553#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000554
555template<class _Callable>
556inline _LIBCPP_INLINE_VISIBILITY
557void
558call_once(once_flag& __flag, _Callable __func)
559{
560 if (__flag.__state_ != ~0ul)
561 {
562 __call_once_param<_Callable> __p(__func);
563 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
564 }
565}
566
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000567#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000568
569_LIBCPP_END_NAMESPACE_STD
570
571#endif // _LIBCPP_MUTEX