1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___MUTEX_ONCE_FLAG_H
10 #define _LIBCPP___MUTEX_ONCE_FLAG_H
13 #include <__functional/invoke.h>
14 #include <__memory/shared_ptr.h> // __libcpp_acquire_load
15 #include <__tuple/tuple_indices.h>
16 #include <__tuple/tuple_size.h>
17 #include <__utility/forward.h>
18 #include <__utility/move.h>
20 #ifndef _LIBCPP_CXX03_LANG
24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25 # pragma GCC system_header
28 _LIBCPP_BEGIN_NAMESPACE_STD
30 struct _LIBCPP_TEMPLATE_VIS once_flag
;
32 #ifndef _LIBCPP_CXX03_LANG
34 template <class _Callable
, class... _Args
>
35 _LIBCPP_HIDE_FROM_ABI
void call_once(once_flag
&, _Callable
&&, _Args
&&...);
37 #else // _LIBCPP_CXX03_LANG
39 template <class _Callable
>
40 _LIBCPP_HIDE_FROM_ABI
void call_once(once_flag
&, _Callable
&);
42 template <class _Callable
>
43 _LIBCPP_HIDE_FROM_ABI
void call_once(once_flag
&, const _Callable
&);
45 #endif // _LIBCPP_CXX03_LANG
47 struct _LIBCPP_TEMPLATE_VIS once_flag
{
48 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
once_flag() _NOEXCEPT
: __state_(_Unset
) {}
49 once_flag(const once_flag
&) = delete;
50 once_flag
& operator=(const once_flag
&) = delete;
52 #if defined(_LIBCPP_ABI_MICROSOFT)
53 typedef uintptr_t _State_type
;
55 typedef unsigned long _State_type
;
58 static const _State_type _Unset
= 0;
59 static const _State_type _Pending
= 1;
60 static const _State_type _Complete
= ~_State_type(0);
65 #ifndef _LIBCPP_CXX03_LANG
66 template <class _Callable
, class... _Args
>
67 friend void call_once(once_flag
&, _Callable
&&, _Args
&&...);
68 #else // _LIBCPP_CXX03_LANG
69 template <class _Callable
>
70 friend void call_once(once_flag
&, _Callable
&);
72 template <class _Callable
>
73 friend void call_once(once_flag
&, const _Callable
&);
74 #endif // _LIBCPP_CXX03_LANG
77 #ifndef _LIBCPP_CXX03_LANG
80 class __call_once_param
{
84 _LIBCPP_HIDE_FROM_ABI
explicit __call_once_param(_Fp
& __f
) : __f_(__f
) {}
86 _LIBCPP_HIDE_FROM_ABI
void operator()() {
87 typedef typename __make_tuple_indices
<tuple_size
<_Fp
>::value
, 1>::type _Index
;
92 template <size_t... _Indices
>
93 _LIBCPP_HIDE_FROM_ABI
void __execute(__tuple_indices
<_Indices
...>) {
94 _VSTD::__invoke(_VSTD::get
<0>(_VSTD::move(__f_
)), _VSTD::get
<_Indices
>(_VSTD::move(__f_
))...);
101 class __call_once_param
{
105 _LIBCPP_HIDE_FROM_ABI
explicit __call_once_param(_Fp
& __f
) : __f_(__f
) {}
107 _LIBCPP_HIDE_FROM_ABI
void operator()() { __f_(); }
113 void _LIBCPP_HIDE_FROM_ABI
__call_once_proxy(void* __vp
) {
114 __call_once_param
<_Fp
>* __p
= static_cast<__call_once_param
<_Fp
>*>(__vp
);
118 _LIBCPP_EXPORTED_FROM_ABI
void __call_once(volatile once_flag::_State_type
&, void*, void (*)(void*));
120 #ifndef _LIBCPP_CXX03_LANG
122 template <class _Callable
, class... _Args
>
123 inline _LIBCPP_HIDE_FROM_ABI
void call_once(once_flag
& __flag
, _Callable
&& __func
, _Args
&&... __args
) {
124 if (__libcpp_acquire_load(&__flag
.__state_
) != once_flag::_Complete
) {
125 typedef tuple
<_Callable
&&, _Args
&&...> _Gp
;
126 _Gp
__f(_VSTD::forward
<_Callable
>(__func
), _VSTD::forward
<_Args
>(__args
)...);
127 __call_once_param
<_Gp
> __p(__f
);
128 std::__call_once(__flag
.__state_
, &__p
, &__call_once_proxy
<_Gp
>);
132 #else // _LIBCPP_CXX03_LANG
134 template <class _Callable
>
135 inline _LIBCPP_HIDE_FROM_ABI
void call_once(once_flag
& __flag
, _Callable
& __func
) {
136 if (__libcpp_acquire_load(&__flag
.__state_
) != once_flag::_Complete
) {
137 __call_once_param
<_Callable
> __p(__func
);
138 std::__call_once(__flag
.__state_
, &__p
, &__call_once_proxy
<_Callable
>);
142 template <class _Callable
>
143 inline _LIBCPP_HIDE_FROM_ABI
void call_once(once_flag
& __flag
, const _Callable
& __func
) {
144 if (__libcpp_acquire_load(&__flag
.__state_
) != once_flag::_Complete
) {
145 __call_once_param
<const _Callable
> __p(__func
);
146 std::__call_once(__flag
.__state_
, &__p
, &__call_once_proxy
<const _Callable
>);
150 #endif // _LIBCPP_CXX03_LANG
152 _LIBCPP_END_NAMESPACE_STD
154 #endif // _LIBCPP___MUTEX_ONCE_FLAG_H