/src/llvm-project-16.0.6.build/include/c++/v1/mutex
Line | Count | Source (jump to first uncovered line) |
1 | | // -*- C++ -*- |
2 | | //===----------------------------------------------------------------------===// |
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; // Only if sizeof...(MutexTypes) == 1 |
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 <__assert> // all public C++ headers provide the assertion handler |
190 | | #include <__config> |
191 | | #include <__memory/shared_ptr.h> |
192 | | #include <__mutex_base> |
193 | | #include <__threading_support> |
194 | | #include <__utility/forward.h> |
195 | | #include <cstdint> |
196 | | #ifndef _LIBCPP_CXX03_LANG |
197 | | # include <tuple> |
198 | | #endif |
199 | | #include <version> |
200 | | |
201 | | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
202 | | # pragma GCC system_header |
203 | | #endif |
204 | | |
205 | | _LIBCPP_PUSH_MACROS |
206 | | #include <__undef_macros> |
207 | | |
208 | | |
209 | | _LIBCPP_BEGIN_NAMESPACE_STD |
210 | | |
211 | | #ifndef _LIBCPP_HAS_NO_THREADS |
212 | | |
213 | | class _LIBCPP_TYPE_VIS recursive_mutex |
214 | | { |
215 | | __libcpp_recursive_mutex_t __m_; |
216 | | |
217 | | public: |
218 | | recursive_mutex(); |
219 | | ~recursive_mutex(); |
220 | | |
221 | | recursive_mutex(const recursive_mutex&) = delete; |
222 | | recursive_mutex& operator=(const recursive_mutex&) = delete; |
223 | | |
224 | | void lock(); |
225 | | bool try_lock() _NOEXCEPT; |
226 | | void unlock() _NOEXCEPT; |
227 | | |
228 | | typedef __libcpp_recursive_mutex_t* native_handle_type; |
229 | | |
230 | | _LIBCPP_INLINE_VISIBILITY |
231 | 0 | native_handle_type native_handle() {return &__m_;} |
232 | | }; |
233 | | |
234 | | class _LIBCPP_TYPE_VIS timed_mutex |
235 | | { |
236 | | mutex __m_; |
237 | | condition_variable __cv_; |
238 | | bool __locked_; |
239 | | public: |
240 | | timed_mutex(); |
241 | | ~timed_mutex(); |
242 | | |
243 | | timed_mutex(const timed_mutex&) = delete; |
244 | | timed_mutex& operator=(const timed_mutex&) = delete; |
245 | | |
246 | | public: |
247 | | void lock(); |
248 | | bool try_lock() _NOEXCEPT; |
249 | | template <class _Rep, class _Period> |
250 | | _LIBCPP_INLINE_VISIBILITY |
251 | | bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
252 | | {return try_lock_until(chrono::steady_clock::now() + __d);} |
253 | | template <class _Clock, class _Duration> |
254 | | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
255 | | bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
256 | | void unlock() _NOEXCEPT; |
257 | | }; |
258 | | |
259 | | template <class _Clock, class _Duration> |
260 | | bool |
261 | | timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
262 | | { |
263 | | using namespace chrono; |
264 | | unique_lock<mutex> __lk(__m_); |
265 | | bool no_timeout = _Clock::now() < __t; |
266 | | while (no_timeout && __locked_) |
267 | | no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; |
268 | | if (!__locked_) |
269 | | { |
270 | | __locked_ = true; |
271 | | return true; |
272 | | } |
273 | | return false; |
274 | | } |
275 | | |
276 | | class _LIBCPP_TYPE_VIS recursive_timed_mutex |
277 | | { |
278 | | mutex __m_; |
279 | | condition_variable __cv_; |
280 | | size_t __count_; |
281 | | __thread_id __id_; |
282 | | public: |
283 | | recursive_timed_mutex(); |
284 | | ~recursive_timed_mutex(); |
285 | | |
286 | | recursive_timed_mutex(const recursive_timed_mutex&) = delete; |
287 | | recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; |
288 | | |
289 | | void lock(); |
290 | | bool try_lock() _NOEXCEPT; |
291 | | template <class _Rep, class _Period> |
292 | | _LIBCPP_INLINE_VISIBILITY |
293 | | bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
294 | | {return try_lock_until(chrono::steady_clock::now() + __d);} |
295 | | template <class _Clock, class _Duration> |
296 | | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
297 | | bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
298 | | void unlock() _NOEXCEPT; |
299 | | }; |
300 | | |
301 | | template <class _Clock, class _Duration> |
302 | | bool |
303 | | recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
304 | | { |
305 | | using namespace chrono; |
306 | | __thread_id __id = this_thread::get_id(); |
307 | | unique_lock<mutex> lk(__m_); |
308 | | if (__id == __id_) |
309 | | { |
310 | | if (__count_ == numeric_limits<size_t>::max()) |
311 | | return false; |
312 | | ++__count_; |
313 | | return true; |
314 | | } |
315 | | bool no_timeout = _Clock::now() < __t; |
316 | | while (no_timeout && __count_ != 0) |
317 | | no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; |
318 | | if (__count_ == 0) |
319 | | { |
320 | | __count_ = 1; |
321 | | __id_ = __id; |
322 | | return true; |
323 | | } |
324 | | return false; |
325 | | } |
326 | | |
327 | | template <class _L0, class _L1> |
328 | | _LIBCPP_HIDE_FROM_ABI int |
329 | | try_lock(_L0& __l0, _L1& __l1) |
330 | | { |
331 | | unique_lock<_L0> __u0(__l0, try_to_lock); |
332 | | if (__u0.owns_lock()) |
333 | | { |
334 | | if (__l1.try_lock()) |
335 | | { |
336 | | __u0.release(); |
337 | | return -1; |
338 | | } |
339 | | else |
340 | | return 1; |
341 | | } |
342 | | return 0; |
343 | | } |
344 | | |
345 | | #ifndef _LIBCPP_CXX03_LANG |
346 | | |
347 | | template <class _L0, class _L1, class _L2, class... _L3> |
348 | | _LIBCPP_HIDE_FROM_ABI int |
349 | | try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) |
350 | | { |
351 | | int __r = 0; |
352 | | unique_lock<_L0> __u0(__l0, try_to_lock); |
353 | | if (__u0.owns_lock()) |
354 | | { |
355 | | __r = std::try_lock(__l1, __l2, __l3...); |
356 | | if (__r == -1) |
357 | | __u0.release(); |
358 | | else |
359 | | ++__r; |
360 | | } |
361 | | return __r; |
362 | | } |
363 | | |
364 | | #endif // _LIBCPP_CXX03_LANG |
365 | | |
366 | | template <class _L0, class _L1> |
367 | | _LIBCPP_HIDE_FROM_ABI void |
368 | | lock(_L0& __l0, _L1& __l1) |
369 | | { |
370 | | while (true) |
371 | | { |
372 | | { |
373 | | unique_lock<_L0> __u0(__l0); |
374 | | if (__l1.try_lock()) |
375 | | { |
376 | | __u0.release(); |
377 | | break; |
378 | | } |
379 | | } |
380 | | __libcpp_thread_yield(); |
381 | | { |
382 | | unique_lock<_L1> __u1(__l1); |
383 | | if (__l0.try_lock()) |
384 | | { |
385 | | __u1.release(); |
386 | | break; |
387 | | } |
388 | | } |
389 | | __libcpp_thread_yield(); |
390 | | } |
391 | | } |
392 | | |
393 | | #ifndef _LIBCPP_CXX03_LANG |
394 | | |
395 | | template <class _L0, class _L1, class _L2, class ..._L3> |
396 | | void |
397 | | __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
398 | | { |
399 | | while (true) |
400 | | { |
401 | | switch (__i) |
402 | | { |
403 | | case 0: |
404 | | { |
405 | | unique_lock<_L0> __u0(__l0); |
406 | | __i = std::try_lock(__l1, __l2, __l3...); |
407 | | if (__i == -1) |
408 | | { |
409 | | __u0.release(); |
410 | | return; |
411 | | } |
412 | | } |
413 | | ++__i; |
414 | | __libcpp_thread_yield(); |
415 | | break; |
416 | | case 1: |
417 | | { |
418 | | unique_lock<_L1> __u1(__l1); |
419 | | __i = std::try_lock(__l2, __l3..., __l0); |
420 | | if (__i == -1) |
421 | | { |
422 | | __u1.release(); |
423 | | return; |
424 | | } |
425 | | } |
426 | | if (__i == sizeof...(_L3) + 1) |
427 | | __i = 0; |
428 | | else |
429 | | __i += 2; |
430 | | __libcpp_thread_yield(); |
431 | | break; |
432 | | default: |
433 | | std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1); |
434 | | return; |
435 | | } |
436 | | } |
437 | | } |
438 | | |
439 | | template <class _L0, class _L1, class _L2, class ..._L3> |
440 | | inline _LIBCPP_INLINE_VISIBILITY |
441 | | void |
442 | | lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
443 | | { |
444 | | std::__lock_first(0, __l0, __l1, __l2, __l3...); |
445 | | } |
446 | | |
447 | | template <class _L0> |
448 | | inline _LIBCPP_INLINE_VISIBILITY |
449 | | void __unlock(_L0& __l0) { |
450 | | __l0.unlock(); |
451 | | } |
452 | | |
453 | | template <class _L0, class _L1> |
454 | | inline _LIBCPP_INLINE_VISIBILITY |
455 | | void __unlock(_L0& __l0, _L1& __l1) { |
456 | | __l0.unlock(); |
457 | | __l1.unlock(); |
458 | | } |
459 | | |
460 | | template <class _L0, class _L1, class _L2, class ..._L3> |
461 | | inline _LIBCPP_INLINE_VISIBILITY |
462 | | void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { |
463 | | __l0.unlock(); |
464 | | __l1.unlock(); |
465 | | _VSTD::__unlock(__l2, __l3...); |
466 | | } |
467 | | |
468 | | #endif // _LIBCPP_CXX03_LANG |
469 | | |
470 | | #if _LIBCPP_STD_VER > 14 |
471 | | template <class ..._Mutexes> |
472 | | class _LIBCPP_TEMPLATE_VIS scoped_lock; |
473 | | |
474 | | template <> |
475 | | class _LIBCPP_TEMPLATE_VIS scoped_lock<> { |
476 | | public: |
477 | 0 | explicit scoped_lock() {} |
478 | | ~scoped_lock() = default; |
479 | | |
480 | | _LIBCPP_INLINE_VISIBILITY |
481 | 0 | explicit scoped_lock(adopt_lock_t) {} |
482 | | |
483 | | scoped_lock(scoped_lock const&) = delete; |
484 | | scoped_lock& operator=(scoped_lock const&) = delete; |
485 | | }; |
486 | | |
487 | | template <class _Mutex> |
488 | | class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { |
489 | | public: |
490 | | typedef _Mutex mutex_type; |
491 | | private: |
492 | | mutex_type& __m_; |
493 | | public: |
494 | | explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) |
495 | | : __m_(__m) {__m_.lock();} |
496 | | |
497 | | ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} |
498 | | |
499 | | _LIBCPP_INLINE_VISIBILITY |
500 | | explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) |
501 | | : __m_(__m) {} |
502 | | |
503 | | scoped_lock(scoped_lock const&) = delete; |
504 | | scoped_lock& operator=(scoped_lock const&) = delete; |
505 | | }; |
506 | | |
507 | | template <class ..._MArgs> |
508 | | class _LIBCPP_TEMPLATE_VIS scoped_lock |
509 | | { |
510 | | static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); |
511 | | typedef tuple<_MArgs&...> _MutexTuple; |
512 | | |
513 | | public: |
514 | | _LIBCPP_INLINE_VISIBILITY |
515 | | explicit scoped_lock(_MArgs&... __margs) |
516 | | : __t_(__margs...) |
517 | | { |
518 | | _VSTD::lock(__margs...); |
519 | | } |
520 | | |
521 | | _LIBCPP_INLINE_VISIBILITY |
522 | | scoped_lock(adopt_lock_t, _MArgs&... __margs) |
523 | | : __t_(__margs...) |
524 | | { |
525 | | } |
526 | | |
527 | | _LIBCPP_INLINE_VISIBILITY |
528 | | ~scoped_lock() { |
529 | | typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; |
530 | | __unlock_unpack(_Indices{}, __t_); |
531 | | } |
532 | | |
533 | | scoped_lock(scoped_lock const&) = delete; |
534 | | scoped_lock& operator=(scoped_lock const&) = delete; |
535 | | |
536 | | private: |
537 | | template <size_t ..._Indx> |
538 | | _LIBCPP_INLINE_VISIBILITY |
539 | | static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { |
540 | | _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); |
541 | | } |
542 | | |
543 | | _MutexTuple __t_; |
544 | | }; |
545 | | _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock); |
546 | | |
547 | | #endif // _LIBCPP_STD_VER > 14 |
548 | | #endif // !_LIBCPP_HAS_NO_THREADS |
549 | | |
550 | | struct _LIBCPP_TEMPLATE_VIS once_flag; |
551 | | |
552 | | #ifndef _LIBCPP_CXX03_LANG |
553 | | |
554 | | template<class _Callable, class... _Args> |
555 | | _LIBCPP_INLINE_VISIBILITY |
556 | | void call_once(once_flag&, _Callable&&, _Args&&...); |
557 | | |
558 | | #else // _LIBCPP_CXX03_LANG |
559 | | |
560 | | template<class _Callable> |
561 | | _LIBCPP_INLINE_VISIBILITY |
562 | | void call_once(once_flag&, _Callable&); |
563 | | |
564 | | template<class _Callable> |
565 | | _LIBCPP_INLINE_VISIBILITY |
566 | | void call_once(once_flag&, const _Callable&); |
567 | | |
568 | | #endif // _LIBCPP_CXX03_LANG |
569 | | |
570 | | struct _LIBCPP_TEMPLATE_VIS once_flag |
571 | | { |
572 | | _LIBCPP_INLINE_VISIBILITY |
573 | | _LIBCPP_CONSTEXPR |
574 | 0 | once_flag() _NOEXCEPT : __state_(0) {} |
575 | | once_flag(const once_flag&) = delete; |
576 | | once_flag& operator=(const once_flag&) = delete; |
577 | | |
578 | | #if defined(_LIBCPP_ABI_MICROSOFT) |
579 | | typedef uintptr_t _State_type; |
580 | | #else |
581 | | typedef unsigned long _State_type; |
582 | | #endif |
583 | | |
584 | | private: |
585 | | _State_type __state_; |
586 | | |
587 | | #ifndef _LIBCPP_CXX03_LANG |
588 | | template<class _Callable, class... _Args> |
589 | | friend |
590 | | void call_once(once_flag&, _Callable&&, _Args&&...); |
591 | | #else // _LIBCPP_CXX03_LANG |
592 | | template<class _Callable> |
593 | | friend |
594 | | void call_once(once_flag&, _Callable&); |
595 | | |
596 | | template<class _Callable> |
597 | | friend |
598 | | void call_once(once_flag&, const _Callable&); |
599 | | #endif // _LIBCPP_CXX03_LANG |
600 | | }; |
601 | | |
602 | | #ifndef _LIBCPP_CXX03_LANG |
603 | | |
604 | | template <class _Fp> |
605 | | class __call_once_param |
606 | | { |
607 | | _Fp& __f_; |
608 | | public: |
609 | | _LIBCPP_INLINE_VISIBILITY |
610 | 180 | explicit __call_once_param(_Fp& __f) : __f_(__f) {} |
611 | | |
612 | | _LIBCPP_INLINE_VISIBILITY |
613 | | void operator()() |
614 | 180 | { |
615 | 180 | typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; |
616 | 180 | __execute(_Index()); |
617 | 180 | } |
618 | | |
619 | | private: |
620 | | template <size_t ..._Indices> |
621 | | _LIBCPP_INLINE_VISIBILITY |
622 | | void __execute(__tuple_indices<_Indices...>) |
623 | 180 | { |
624 | 180 | _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); |
625 | 180 | } |
626 | | }; |
627 | | |
628 | | #else |
629 | | |
630 | | template <class _Fp> |
631 | | class __call_once_param |
632 | | { |
633 | | _Fp& __f_; |
634 | | public: |
635 | | _LIBCPP_INLINE_VISIBILITY |
636 | | explicit __call_once_param(_Fp& __f) : __f_(__f) {} |
637 | | |
638 | | _LIBCPP_INLINE_VISIBILITY |
639 | | void operator()() |
640 | | { |
641 | | __f_(); |
642 | | } |
643 | | }; |
644 | | |
645 | | #endif |
646 | | |
647 | | template <class _Fp> |
648 | | void _LIBCPP_INLINE_VISIBILITY |
649 | | __call_once_proxy(void* __vp) |
650 | 180 | { |
651 | 180 | __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); |
652 | 180 | (*__p)(); |
653 | 180 | } |
654 | | |
655 | | _LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, |
656 | | void (*)(void*)); |
657 | | |
658 | | #ifndef _LIBCPP_CXX03_LANG |
659 | | |
660 | | template<class _Callable, class... _Args> |
661 | | inline _LIBCPP_INLINE_VISIBILITY |
662 | | void |
663 | | call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) |
664 | 25.5k | { |
665 | 25.5k | if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) |
666 | 180 | { |
667 | 180 | typedef tuple<_Callable&&, _Args&&...> _Gp; |
668 | 180 | _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); |
669 | 180 | __call_once_param<_Gp> __p(__f); |
670 | 180 | std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); |
671 | 180 | } |
672 | 25.5k | } |
673 | | |
674 | | #else // _LIBCPP_CXX03_LANG |
675 | | |
676 | | template<class _Callable> |
677 | | inline _LIBCPP_INLINE_VISIBILITY |
678 | | void |
679 | | call_once(once_flag& __flag, _Callable& __func) |
680 | | { |
681 | | if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) |
682 | | { |
683 | | __call_once_param<_Callable> __p(__func); |
684 | | std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); |
685 | | } |
686 | | } |
687 | | |
688 | | template<class _Callable> |
689 | | inline _LIBCPP_INLINE_VISIBILITY |
690 | | void |
691 | | call_once(once_flag& __flag, const _Callable& __func) |
692 | | { |
693 | | if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) |
694 | | { |
695 | | __call_once_param<const _Callable> __p(__func); |
696 | | std::__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); |
697 | | } |
698 | | } |
699 | | |
700 | | #endif // _LIBCPP_CXX03_LANG |
701 | | |
702 | | _LIBCPP_END_NAMESPACE_STD |
703 | | |
704 | | _LIBCPP_POP_MACROS |
705 | | |
706 | | #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
707 | | # include <concepts> |
708 | | # include <functional> |
709 | | # include <type_traits> |
710 | | #endif |
711 | | |
712 | | #endif // _LIBCPP_MUTEX |