Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / include / __mutex / once_flag.h
blob086f75ca4f8148035fd15394bf0b61523c56ace3
1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___MUTEX_ONCE_FLAG_H
10 #define _LIBCPP___MUTEX_ONCE_FLAG_H
12 #include <__config>
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>
19 #include <cstdint>
20 #ifndef _LIBCPP_CXX03_LANG
21 # include <tuple>
22 #endif
24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25 # pragma GCC system_header
26 #endif
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;
54 #else
55 typedef unsigned long _State_type;
56 #endif
58 static const _State_type _Unset = 0;
59 static const _State_type _Pending = 1;
60 static const _State_type _Complete = ~_State_type(0);
62 private:
63 _State_type __state_;
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
79 template <class _Fp>
80 class __call_once_param {
81 _Fp& __f_;
83 public:
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;
88 __execute(_Index());
91 private:
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_))...);
98 #else
100 template <class _Fp>
101 class __call_once_param {
102 _Fp& __f_;
104 public:
105 _LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}
107 _LIBCPP_HIDE_FROM_ABI void operator()() { __f_(); }
110 #endif
112 template <class _Fp>
113 void _LIBCPP_HIDE_FROM_ABI __call_once_proxy(void* __vp) {
114 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
115 (*__p)();
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