blob: 0adf1e69bf2af52f37a5f56284facf939c9a71c4 [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
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000445void call_once(once_flag&, _Callable&);
446
447template<class _Callable>
448_LIBCPP_INLINE_VISIBILITY
449void call_once(once_flag&, const _Callable&);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000450
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000451#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000452
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000453struct _LIBCPP_TYPE_VIS_ONLY once_flag
Howard Hinnantc51e1022010-05-11 19:42:16 +0000454{
Howard Hinnantf5f99992010-09-22 18:02:38 +0000455 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbd05d6a2012-07-21 16:13:09 +0000456 _LIBCPP_CONSTEXPR
457 once_flag() _NOEXCEPT : __state_(0) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000458
459private:
460 once_flag(const once_flag&); // = delete;
461 once_flag& operator=(const once_flag&); // = delete;
462
463 unsigned long __state_;
464
465#ifndef _LIBCPP_HAS_NO_VARIADICS
466 template<class _Callable, class... _Args>
467 friend
468 void call_once(once_flag&, _Callable&&, _Args&&...);
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000469#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470 template<class _Callable>
471 friend
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000472 void call_once(once_flag&, _Callable&);
473
474 template<class _Callable>
475 friend
476 void call_once(once_flag&, const _Callable&);
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000477#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478};
479
Howard Hinnant51d62e02011-05-16 19:05:11 +0000480#ifndef _LIBCPP_HAS_NO_VARIADICS
481
Howard Hinnantc834c512011-11-29 18:15:50 +0000482template <class _Fp>
Howard Hinnant51d62e02011-05-16 19:05:11 +0000483class __call_once_param
484{
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000485 _Fp& __f_;
Howard Hinnant51d62e02011-05-16 19:05:11 +0000486public:
Howard Hinnant51d62e02011-05-16 19:05:11 +0000487 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000488 explicit __call_once_param(_Fp& __f) : __f_(__f) {}
Howard Hinnant51d62e02011-05-16 19:05:11 +0000489
490 _LIBCPP_INLINE_VISIBILITY
491 void operator()()
492 {
Howard Hinnantc834c512011-11-29 18:15:50 +0000493 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
Howard Hinnant51d62e02011-05-16 19:05:11 +0000494 __execute(_Index());
495 }
496
497private:
498 template <size_t ..._Indices>
499 _LIBCPP_INLINE_VISIBILITY
500 void __execute(__tuple_indices<_Indices...>)
501 {
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000502 __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
Howard Hinnant51d62e02011-05-16 19:05:11 +0000503 }
504};
505
506#else
507
Howard Hinnantc834c512011-11-29 18:15:50 +0000508template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509class __call_once_param
510{
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000511 _Fp& __f_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000512public:
Howard Hinnantf5f99992010-09-22 18:02:38 +0000513 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000514 explicit __call_once_param(_Fp& __f) : __f_(__f) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000515
Howard Hinnantf5f99992010-09-22 18:02:38 +0000516 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000517 void operator()()
518 {
519 __f_();
520 }
521};
522
Howard Hinnant51d62e02011-05-16 19:05:11 +0000523#endif
524
Howard Hinnantc834c512011-11-29 18:15:50 +0000525template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000526void
527__call_once_proxy(void* __vp)
528{
Howard Hinnantc834c512011-11-29 18:15:50 +0000529 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000530 (*__p)();
531}
532
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000533_LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000534
535#ifndef _LIBCPP_HAS_NO_VARIADICS
536
537template<class _Callable, class... _Args>
538inline _LIBCPP_INLINE_VISIBILITY
539void
540call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
541{
Howard Hinnant28b24882011-12-01 20:21:04 +0000542 if (__flag.__state_ != ~0ul)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000543 {
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000544 typedef tuple<_Callable&&, _Args&&...> _Gp;
545 _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
546 __call_once_param<_Gp> __p(__f);
Howard Hinnantc834c512011-11-29 18:15:50 +0000547 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000548 }
549}
550
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000551#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000552
553template<class _Callable>
554inline _LIBCPP_INLINE_VISIBILITY
555void
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000556call_once(once_flag& __flag, _Callable& __func)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000557{
558 if (__flag.__state_ != ~0ul)
559 {
560 __call_once_param<_Callable> __p(__func);
561 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
562 }
563}
564
Eric Fiselier1e88fdc2015-06-13 02:23:00 +0000565template<class _Callable>
566inline _LIBCPP_INLINE_VISIBILITY
567void
568call_once(once_flag& __flag, const _Callable& __func)
569{
570 if (__flag.__state_ != ~0ul)
571 {
572 __call_once_param<const _Callable> __p(__func);
573 __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
574 }
575}
576
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000577#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000578
579_LIBCPP_END_NAMESPACE_STD
580
581#endif // _LIBCPP_MUTEX