/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/include/mutex
Line | Count | Source (jump to first uncovered line) |
1 | | // -*- C++ -*- |
2 | | //===--------------------------- mutex ------------------------------------===// |
3 | | // |
4 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | | // See https://llvm.org/LICENSE.txt for license information. |
6 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #ifndef _LIBCPP_MUTEX |
11 | | #define _LIBCPP_MUTEX |
12 | | |
13 | | /* |
14 | | mutex synopsis |
15 | | |
16 | | namespace std |
17 | | { |
18 | | |
19 | | class mutex |
20 | | { |
21 | | public: |
22 | | constexpr mutex() noexcept; |
23 | | ~mutex(); |
24 | | |
25 | | mutex(const mutex&) = delete; |
26 | | mutex& operator=(const mutex&) = delete; |
27 | | |
28 | | void lock(); |
29 | | bool try_lock(); |
30 | | void unlock(); |
31 | | |
32 | | typedef pthread_mutex_t* native_handle_type; |
33 | | native_handle_type native_handle(); |
34 | | }; |
35 | | |
36 | | class recursive_mutex |
37 | | { |
38 | | public: |
39 | | recursive_mutex(); |
40 | | ~recursive_mutex(); |
41 | | |
42 | | recursive_mutex(const recursive_mutex&) = delete; |
43 | | recursive_mutex& operator=(const recursive_mutex&) = delete; |
44 | | |
45 | | void lock(); |
46 | | bool try_lock() noexcept; |
47 | | void unlock(); |
48 | | |
49 | | typedef pthread_mutex_t* native_handle_type; |
50 | | native_handle_type native_handle(); |
51 | | }; |
52 | | |
53 | | class timed_mutex |
54 | | { |
55 | | public: |
56 | | timed_mutex(); |
57 | | ~timed_mutex(); |
58 | | |
59 | | timed_mutex(const timed_mutex&) = delete; |
60 | | timed_mutex& operator=(const timed_mutex&) = delete; |
61 | | |
62 | | void lock(); |
63 | | bool try_lock(); |
64 | | template <class Rep, class Period> |
65 | | bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
66 | | template <class Clock, class Duration> |
67 | | bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
68 | | void unlock(); |
69 | | }; |
70 | | |
71 | | class recursive_timed_mutex |
72 | | { |
73 | | public: |
74 | | recursive_timed_mutex(); |
75 | | ~recursive_timed_mutex(); |
76 | | |
77 | | recursive_timed_mutex(const recursive_timed_mutex&) = delete; |
78 | | recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; |
79 | | |
80 | | void lock(); |
81 | | bool try_lock() noexcept; |
82 | | template <class Rep, class Period> |
83 | | bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
84 | | template <class Clock, class Duration> |
85 | | bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
86 | | void unlock(); |
87 | | }; |
88 | | |
89 | | struct defer_lock_t { explicit defer_lock_t() = default; }; |
90 | | struct try_to_lock_t { explicit try_to_lock_t() = default; }; |
91 | | struct adopt_lock_t { explicit adopt_lock_t() = default; }; |
92 | | |
93 | | inline constexpr defer_lock_t defer_lock{}; |
94 | | inline constexpr try_to_lock_t try_to_lock{}; |
95 | | inline constexpr adopt_lock_t adopt_lock{}; |
96 | | |
97 | | template <class Mutex> |
98 | | class lock_guard |
99 | | { |
100 | | public: |
101 | | typedef Mutex mutex_type; |
102 | | |
103 | | explicit lock_guard(mutex_type& m); |
104 | | lock_guard(mutex_type& m, adopt_lock_t); |
105 | | ~lock_guard(); |
106 | | |
107 | | lock_guard(lock_guard const&) = delete; |
108 | | lock_guard& operator=(lock_guard const&) = delete; |
109 | | }; |
110 | | |
111 | | template <class... MutexTypes> |
112 | | class scoped_lock // C++17 |
113 | | { |
114 | | public: |
115 | | using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex |
116 | | |
117 | | explicit scoped_lock(MutexTypes&... m); |
118 | | scoped_lock(adopt_lock_t, MutexTypes&... m); |
119 | | ~scoped_lock(); |
120 | | scoped_lock(scoped_lock const&) = delete; |
121 | | scoped_lock& operator=(scoped_lock const&) = delete; |
122 | | private: |
123 | | tuple<MutexTypes&...> pm; // exposition only |
124 | | }; |
125 | | |
126 | | template <class Mutex> |
127 | | class unique_lock |
128 | | { |
129 | | public: |
130 | | typedef Mutex mutex_type; |
131 | | unique_lock() noexcept; |
132 | | explicit unique_lock(mutex_type& m); |
133 | | unique_lock(mutex_type& m, defer_lock_t) noexcept; |
134 | | unique_lock(mutex_type& m, try_to_lock_t); |
135 | | unique_lock(mutex_type& m, adopt_lock_t); |
136 | | template <class Clock, class Duration> |
137 | | unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); |
138 | | template <class Rep, class Period> |
139 | | unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); |
140 | | ~unique_lock(); |
141 | | |
142 | | unique_lock(unique_lock const&) = delete; |
143 | | unique_lock& operator=(unique_lock const&) = delete; |
144 | | |
145 | | unique_lock(unique_lock&& u) noexcept; |
146 | | unique_lock& operator=(unique_lock&& u) noexcept; |
147 | | |
148 | | void lock(); |
149 | | bool try_lock(); |
150 | | |
151 | | template <class Rep, class Period> |
152 | | bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
153 | | template <class Clock, class Duration> |
154 | | bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
155 | | |
156 | | void unlock(); |
157 | | |
158 | | void swap(unique_lock& u) noexcept; |
159 | | mutex_type* release() noexcept; |
160 | | |
161 | | bool owns_lock() const noexcept; |
162 | | explicit operator bool () const noexcept; |
163 | | mutex_type* mutex() const noexcept; |
164 | | }; |
165 | | |
166 | | template <class Mutex> |
167 | | void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; |
168 | | |
169 | | template <class L1, class L2, class... L3> |
170 | | int try_lock(L1&, L2&, L3&...); |
171 | | template <class L1, class L2, class... L3> |
172 | | void lock(L1&, L2&, L3&...); |
173 | | |
174 | | struct once_flag |
175 | | { |
176 | | constexpr once_flag() noexcept; |
177 | | |
178 | | once_flag(const once_flag&) = delete; |
179 | | once_flag& operator=(const once_flag&) = delete; |
180 | | }; |
181 | | |
182 | | template<class Callable, class ...Args> |
183 | | void call_once(once_flag& flag, Callable&& func, Args&&... args); |
184 | | |
185 | | } // std |
186 | | |
187 | | */ |
188 | | |
189 | | #include <__config> |
190 | | #include <__mutex_base> |
191 | | #include <cstdint> |
192 | | #include <functional> |
193 | | #include <memory> |
194 | | #ifndef _LIBCPP_CXX03_LANG |
195 | | #include <tuple> |
196 | | #endif |
197 | | #include <version> |
198 | | #include <__threading_support> |
199 | | |
200 | | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
201 | | #pragma GCC system_header |
202 | | #endif |
203 | | |
204 | | _LIBCPP_PUSH_MACROS |
205 | | #include <__undef_macros> |
206 | | |
207 | | |
208 | | _LIBCPP_BEGIN_NAMESPACE_STD |
209 | | |
210 | | #ifndef _LIBCPP_HAS_NO_THREADS |
211 | | |
212 | | class _LIBCPP_TYPE_VIS recursive_mutex |
213 | | { |
214 | | __libcpp_recursive_mutex_t __m_; |
215 | | |
216 | | public: |
217 | | recursive_mutex(); |
218 | | ~recursive_mutex(); |
219 | | |
220 | | private: |
221 | | recursive_mutex(const recursive_mutex&); // = delete; |
222 | | recursive_mutex& operator=(const recursive_mutex&); // = delete; |
223 | | |
224 | | public: |
225 | | void lock(); |
226 | | bool try_lock() _NOEXCEPT; |
227 | | void unlock() _NOEXCEPT; |
228 | | |
229 | | typedef __libcpp_recursive_mutex_t* native_handle_type; |
230 | | |
231 | | _LIBCPP_INLINE_VISIBILITY |
232 | 0 | native_handle_type native_handle() {return &__m_;} |
233 | | }; |
234 | | |
235 | | class _LIBCPP_TYPE_VIS timed_mutex |
236 | | { |
237 | | mutex __m_; |
238 | | condition_variable __cv_; |
239 | | bool __locked_; |
240 | | public: |
241 | | timed_mutex(); |
242 | | ~timed_mutex(); |
243 | | |
244 | | private: |
245 | | timed_mutex(const timed_mutex&); // = delete; |
246 | | timed_mutex& operator=(const timed_mutex&); // = delete; |
247 | | |
248 | | public: |
249 | | void lock(); |
250 | | bool try_lock() _NOEXCEPT; |
251 | | template <class _Rep, class _Period> |
252 | | _LIBCPP_INLINE_VISIBILITY |
253 | | bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
254 | | {return try_lock_until(chrono::steady_clock::now() + __d);} |
255 | | template <class _Clock, class _Duration> |
256 | | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
257 | | bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
258 | | void unlock() _NOEXCEPT; |
259 | | }; |
260 | | |
261 | | template <class _Clock, class _Duration> |
262 | | bool |
263 | | timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
264 | | { |
265 | | using namespace chrono; |
266 | | unique_lock<mutex> __lk(__m_); |
267 | | bool no_timeout = _Clock::now() < __t; |
268 | | while (no_timeout && __locked_) |
269 | | no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; |
270 | | if (!__locked_) |
271 | | { |
272 | | __locked_ = true; |
273 | | return true; |
274 | | } |
275 | | return false; |
276 | | } |
277 | | |
278 | | class _LIBCPP_TYPE_VIS recursive_timed_mutex |
279 | | { |
280 | | mutex __m_; |
281 | | condition_variable __cv_; |
282 | | size_t __count_; |
283 | | __thread_id __id_; |
284 | | public: |
285 | | recursive_timed_mutex(); |
286 | | ~recursive_timed_mutex(); |
287 | | |
288 | | private: |
289 | | recursive_timed_mutex(const recursive_timed_mutex&); // = delete; |
290 | | recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; |
291 | | |
292 | | public: |
293 | | void lock(); |
294 | | bool try_lock() _NOEXCEPT; |
295 | | template <class _Rep, class _Period> |
296 | | _LIBCPP_INLINE_VISIBILITY |
297 | | bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
298 | | {return try_lock_until(chrono::steady_clock::now() + __d);} |
299 | | template <class _Clock, class _Duration> |
300 | | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
301 | | bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
302 | | void unlock() _NOEXCEPT; |
303 | | }; |
304 | | |
305 | | template <class _Clock, class _Duration> |
306 | | bool |
307 | | recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
308 | | { |
309 | | using namespace chrono; |
310 | | __thread_id __id = this_thread::get_id(); |
311 | | unique_lock<mutex> lk(__m_); |
312 | | if (__id == __id_) |
313 | | { |
314 | | if (__count_ == numeric_limits<size_t>::max()) |
315 | | return false; |
316 | | ++__count_; |
317 | | return true; |
318 | | } |
319 | | bool no_timeout = _Clock::now() < __t; |
320 | | while (no_timeout && __count_ != 0) |
321 | | no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; |
322 | | if (__count_ == 0) |
323 | | { |
324 | | __count_ = 1; |
325 | | __id_ = __id; |
326 | | return true; |
327 | | } |
328 | | return false; |
329 | | } |
330 | | |
331 | | template <class _L0, class _L1> |
332 | | int |
333 | | try_lock(_L0& __l0, _L1& __l1) |
334 | | { |
335 | | unique_lock<_L0> __u0(__l0, try_to_lock); |
336 | | if (__u0.owns_lock()) |
337 | | { |
338 | | if (__l1.try_lock()) |
339 | | { |
340 | | __u0.release(); |
341 | | return -1; |
342 | | } |
343 | | else |
344 | | return 1; |
345 | | } |
346 | | return 0; |
347 | | } |
348 | | |
349 | | #ifndef _LIBCPP_CXX03_LANG |
350 | | |
351 | | template <class _L0, class _L1, class _L2, class... _L3> |
352 | | int |
353 | | try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) |
354 | | { |
355 | | int __r = 0; |
356 | | unique_lock<_L0> __u0(__l0, try_to_lock); |
357 | | if (__u0.owns_lock()) |
358 | | { |
359 | | __r = try_lock(__l1, __l2, __l3...); |
360 | | if (__r == -1) |
361 | | __u0.release(); |
362 | | else |
363 | | ++__r; |
364 | | } |
365 | | return __r; |
366 | | } |
367 | | |
368 | | #endif // _LIBCPP_CXX03_LANG |
369 | | |
370 | | template <class _L0, class _L1> |
371 | | void |
372 | | lock(_L0& __l0, _L1& __l1) |
373 | | { |
374 | | while (true) |
375 | | { |
376 | | { |
377 | | unique_lock<_L0> __u0(__l0); |
378 | | if (__l1.try_lock()) |
379 | | { |
380 | | __u0.release(); |
381 | | break; |
382 | | } |
383 | | } |
384 | | __libcpp_thread_yield(); |
385 | | { |
386 | | unique_lock<_L1> __u1(__l1); |
387 | | if (__l0.try_lock()) |
388 | | { |
389 | | __u1.release(); |
390 | | break; |
391 | | } |
392 | | } |
393 | | __libcpp_thread_yield(); |
394 | | } |
395 | | } |
396 | | |
397 | | #ifndef _LIBCPP_CXX03_LANG |
398 | | |
399 | | template <class _L0, class _L1, class _L2, class ..._L3> |
400 | | void |
401 | | __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
402 | | { |
403 | | while (true) |
404 | | { |
405 | | switch (__i) |
406 | | { |
407 | | case 0: |
408 | | { |
409 | | unique_lock<_L0> __u0(__l0); |
410 | | __i = try_lock(__l1, __l2, __l3...); |
411 | | if (__i == -1) |
412 | | { |
413 | | __u0.release(); |
414 | | return; |
415 | | } |
416 | | } |
417 | | ++__i; |
418 | | __libcpp_thread_yield(); |
419 | | break; |
420 | | case 1: |
421 | | { |
422 | | unique_lock<_L1> __u1(__l1); |
423 | | __i = try_lock(__l2, __l3..., __l0); |
424 | | if (__i == -1) |
425 | | { |
426 | | __u1.release(); |
427 | | return; |
428 | | } |
429 | | } |
430 | | if (__i == sizeof...(_L3) + 1) |
431 | | __i = 0; |
432 | | else |
433 | | __i += 2; |
434 | | __libcpp_thread_yield(); |
435 | | break; |
436 | | default: |
437 | | __lock_first(__i - 2, __l2, __l3..., __l0, __l1); |
438 | | return; |
439 | | } |
440 | | } |
441 | | } |
442 | | |
443 | | template <class _L0, class _L1, class _L2, class ..._L3> |
444 | | inline _LIBCPP_INLINE_VISIBILITY |
445 | | void |
446 | | lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
447 | | { |
448 | | __lock_first(0, __l0, __l1, __l2, __l3...); |
449 | | } |
450 | | |
451 | | template <class _L0> |
452 | | inline _LIBCPP_INLINE_VISIBILITY |
453 | | void __unlock(_L0& __l0) { |
454 | | __l0.unlock(); |
455 | | } |
456 | | |
457 | | template <class _L0, class _L1> |
458 | | inline _LIBCPP_INLINE_VISIBILITY |
459 | | void __unlock(_L0& __l0, _L1& __l1) { |
460 | | __l0.unlock(); |
461 | | __l1.unlock(); |
462 | | } |
463 | | |
464 | | template <class _L0, class _L1, class _L2, class ..._L3> |
465 | | inline _LIBCPP_INLINE_VISIBILITY |
466 | | void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { |
467 | | __l0.unlock(); |
468 | | __l1.unlock(); |
469 | | _VSTD::__unlock(__l2, __l3...); |
470 | | } |
471 | | |
472 | | #endif // _LIBCPP_CXX03_LANG |
473 | | |
474 | | #if _LIBCPP_STD_VER > 14 |
475 | | template <class ..._Mutexes> |
476 | | class _LIBCPP_TEMPLATE_VIS scoped_lock; |
477 | | |
478 | | template <> |
479 | | class _LIBCPP_TEMPLATE_VIS scoped_lock<> { |
480 | | public: |
481 | | explicit scoped_lock() {} |
482 | | ~scoped_lock() = default; |
483 | | |
484 | | _LIBCPP_INLINE_VISIBILITY |
485 | | explicit scoped_lock(adopt_lock_t) {} |
486 | | |
487 | | scoped_lock(scoped_lock const&) = delete; |
488 | | scoped_lock& operator=(scoped_lock const&) = delete; |
489 | | }; |
490 | | |
491 | | template <class _Mutex> |
492 | | class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { |
493 | | public: |
494 | | typedef _Mutex mutex_type; |
495 | | private: |
496 | | mutex_type& __m_; |
497 | | public: |
498 | | explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) |
499 | | : __m_(__m) {__m_.lock();} |
500 | | |
501 | | ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} |
502 | | |
503 | | _LIBCPP_INLINE_VISIBILITY |
504 | | explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) |
505 | | : __m_(__m) {} |
506 | | |
507 | | scoped_lock(scoped_lock const&) = delete; |
508 | | scoped_lock& operator=(scoped_lock const&) = delete; |
509 | | }; |
510 | | |
511 | | template <class ..._MArgs> |
512 | | class _LIBCPP_TEMPLATE_VIS scoped_lock |
513 | | { |
514 | | static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); |
515 | | typedef tuple<_MArgs&...> _MutexTuple; |
516 | | |
517 | | public: |
518 | | _LIBCPP_INLINE_VISIBILITY |
519 | | explicit scoped_lock(_MArgs&... __margs) |
520 | | : __t_(__margs...) |
521 | | { |
522 | | _VSTD::lock(__margs...); |
523 | | } |
524 | | |
525 | | _LIBCPP_INLINE_VISIBILITY |
526 | | scoped_lock(adopt_lock_t, _MArgs&... __margs) |
527 | | : __t_(__margs...) |
528 | | { |
529 | | } |
530 | | |
531 | | _LIBCPP_INLINE_VISIBILITY |
532 | | ~scoped_lock() { |
533 | | typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; |
534 | | __unlock_unpack(_Indices{}, __t_); |
535 | | } |
536 | | |
537 | | scoped_lock(scoped_lock const&) = delete; |
538 | | scoped_lock& operator=(scoped_lock const&) = delete; |
539 | | |
540 | | private: |
541 | | template <size_t ..._Indx> |
542 | | _LIBCPP_INLINE_VISIBILITY |
543 | | static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { |
544 | | _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); |
545 | | } |
546 | | |
547 | | _MutexTuple __t_; |
548 | | }; |
549 | | |
550 | | #endif // _LIBCPP_STD_VER > 14 |
551 | | #endif // !_LIBCPP_HAS_NO_THREADS |
552 | | |
553 | | struct _LIBCPP_TEMPLATE_VIS once_flag; |
554 | | |
555 | | #ifndef _LIBCPP_CXX03_LANG |
556 | | |
557 | | template<class _Callable, class... _Args> |
558 | | _LIBCPP_INLINE_VISIBILITY |
559 | | void call_once(once_flag&, _Callable&&, _Args&&...); |
560 | | |
561 | | #else // _LIBCPP_CXX03_LANG |
562 | | |
563 | | template<class _Callable> |
564 | | _LIBCPP_INLINE_VISIBILITY |
565 | | void call_once(once_flag&, _Callable&); |
566 | | |
567 | | template<class _Callable> |
568 | | _LIBCPP_INLINE_VISIBILITY |
569 | | void call_once(once_flag&, const _Callable&); |
570 | | |
571 | | #endif // _LIBCPP_CXX03_LANG |
572 | | |
573 | | struct _LIBCPP_TEMPLATE_VIS once_flag |
574 | | { |
575 | | _LIBCPP_INLINE_VISIBILITY |
576 | | _LIBCPP_CONSTEXPR |
577 | | once_flag() _NOEXCEPT : __state_(0) {} |
578 | | |
579 | | #if defined(_LIBCPP_ABI_MICROSOFT) |
580 | | typedef uintptr_t _State_type; |
581 | | #else |
582 | | typedef unsigned long _State_type; |
583 | | #endif |
584 | | |
585 | | |
586 | | private: |
587 | | once_flag(const once_flag&); // = delete; |
588 | | once_flag& operator=(const once_flag&); // = delete; |
589 | | |
590 | | _State_type __state_; |
591 | | |
592 | | #ifndef _LIBCPP_CXX03_LANG |
593 | | template<class _Callable, class... _Args> |
594 | | friend |
595 | | void call_once(once_flag&, _Callable&&, _Args&&...); |
596 | | #else // _LIBCPP_CXX03_LANG |
597 | | template<class _Callable> |
598 | | friend |
599 | | void call_once(once_flag&, _Callable&); |
600 | | |
601 | | template<class _Callable> |
602 | | friend |
603 | | void call_once(once_flag&, const _Callable&); |
604 | | #endif // _LIBCPP_CXX03_LANG |
605 | | }; |
606 | | |
607 | | #ifndef _LIBCPP_CXX03_LANG |
608 | | |
609 | | template <class _Fp> |
610 | | class __call_once_param |
611 | | { |
612 | | _Fp& __f_; |
613 | | public: |
614 | | _LIBCPP_INLINE_VISIBILITY |
615 | 238k | explicit __call_once_param(_Fp& __f) : __f_(__f) {} |
616 | | |
617 | | _LIBCPP_INLINE_VISIBILITY |
618 | | void operator()() |
619 | 238k | { |
620 | 238k | typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; |
621 | 238k | __execute(_Index()); |
622 | 238k | } |
623 | | |
624 | | private: |
625 | | template <size_t ..._Indices> |
626 | | _LIBCPP_INLINE_VISIBILITY |
627 | | void __execute(__tuple_indices<_Indices...>) |
628 | 238k | { |
629 | 238k | __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); |
630 | 238k | } |
631 | | }; |
632 | | |
633 | | #else |
634 | | |
635 | | template <class _Fp> |
636 | | class __call_once_param |
637 | | { |
638 | | _Fp& __f_; |
639 | | public: |
640 | | _LIBCPP_INLINE_VISIBILITY |
641 | | explicit __call_once_param(_Fp& __f) : __f_(__f) {} |
642 | | |
643 | | _LIBCPP_INLINE_VISIBILITY |
644 | | void operator()() |
645 | | { |
646 | | __f_(); |
647 | | } |
648 | | }; |
649 | | |
650 | | #endif |
651 | | |
652 | | template <class _Fp> |
653 | | void _LIBCPP_INLINE_VISIBILITY |
654 | | __call_once_proxy(void* __vp) |
655 | 238k | { |
656 | 238k | __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); |
657 | 238k | (*__p)(); |
658 | 238k | } |
659 | | |
660 | | _LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, |
661 | | void (*)(void*)); |
662 | | |
663 | | #ifndef _LIBCPP_CXX03_LANG |
664 | | |
665 | | template<class _Callable, class... _Args> |
666 | | inline _LIBCPP_INLINE_VISIBILITY |
667 | | void |
668 | | call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) |
669 | 19.6M | { |
670 | 19.6M | if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) |
671 | 238k | { |
672 | 238k | typedef tuple<_Callable&&, _Args&&...> _Gp; |
673 | 238k | _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); |
674 | 238k | __call_once_param<_Gp> __p(__f); |
675 | 238k | __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); |
676 | 238k | } |
677 | 19.6M | } |
678 | | |
679 | | #else // _LIBCPP_CXX03_LANG |
680 | | |
681 | | template<class _Callable> |
682 | | inline _LIBCPP_INLINE_VISIBILITY |
683 | | void |
684 | | call_once(once_flag& __flag, _Callable& __func) |
685 | | { |
686 | | if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) |
687 | | { |
688 | | __call_once_param<_Callable> __p(__func); |
689 | | __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); |
690 | | } |
691 | | } |
692 | | |
693 | | template<class _Callable> |
694 | | inline _LIBCPP_INLINE_VISIBILITY |
695 | | void |
696 | | call_once(once_flag& __flag, const _Callable& __func) |
697 | | { |
698 | | if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) |
699 | | { |
700 | | __call_once_param<const _Callable> __p(__func); |
701 | | __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); |
702 | | } |
703 | | } |
704 | | |
705 | | #endif // _LIBCPP_CXX03_LANG |
706 | | |
707 | | _LIBCPP_END_NAMESPACE_STD |
708 | | |
709 | | _LIBCPP_POP_MACROS |
710 | | |
711 | | #endif // _LIBCPP_MUTEX |