1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___MUTEX_ONCE_FLAG_H
#define _LIBCPP___MUTEX_ONCE_FLAG_H
#include <__config>
#include <__functional/invoke.h>
#include <__memory/shared_ptr.h> // __libcpp_acquire_load
#include <__tuple/tuple_indices.h>
#include <__tuple/tuple_size.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <cstdint>
#ifndef _LIBCPP_CXX03_LANG
# include <tuple>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS once_flag;
#ifndef _LIBCPP_CXX03_LANG
template <class _Callable, class... _Args>
_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&&, _Args&&...);
#else // _LIBCPP_CXX03_LANG
template <class _Callable>
_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&);
template <class _Callable>
_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, const _Callable&);
#endif // _LIBCPP_CXX03_LANG
struct _LIBCPP_TEMPLATE_VIS once_flag {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR once_flag() _NOEXCEPT : __state_(_Unset) {}
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
#if defined(_LIBCPP_ABI_MICROSOFT)
typedef uintptr_t _State_type;
#else
typedef unsigned long _State_type;
#endif
static const _State_type _Unset = 0;
static const _State_type _Pending = 1;
static const _State_type _Complete = ~_State_type(0);
private:
_State_type __state_;
#ifndef _LIBCPP_CXX03_LANG
template <class _Callable, class... _Args>
friend void call_once(once_flag&, _Callable&&, _Args&&...);
#else // _LIBCPP_CXX03_LANG
template <class _Callable>
friend void call_once(once_flag&, _Callable&);
template <class _Callable>
friend void call_once(once_flag&, const _Callable&);
#endif // _LIBCPP_CXX03_LANG
};
#ifndef _LIBCPP_CXX03_LANG
template <class _Fp>
class __call_once_param {
_Fp& __f_;
public:
_LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}
_LIBCPP_HIDE_FROM_ABI void operator()() {
typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
__execute(_Index());
}
private:
template <size_t... _Indices>
_LIBCPP_HIDE_FROM_ABI void __execute(__tuple_indices<_Indices...>) {
std::__invoke(std::get<0>(std::move(__f_)), std::get<_Indices>(std::move(__f_))...);
}
};
#else
template <class _Fp>
class __call_once_param {
_Fp& __f_;
public:
_LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}
_LIBCPP_HIDE_FROM_ABI void operator()() { __f_(); }
};
#endif
template <class _Fp>
void _LIBCPP_HIDE_FROM_ABI __call_once_proxy(void* __vp) {
__call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
(*__p)();
}
_LIBCPP_EXPORTED_FROM_ABI void __call_once(volatile once_flag::_State_type&, void*, void (*)(void*));
#ifndef _LIBCPP_CXX03_LANG
template <class _Callable, class... _Args>
inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) {
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
typedef tuple<_Callable&&, _Args&&...> _Gp;
_Gp __f(std::forward<_Callable>(__func), std::forward<_Args>(__args)...);
__call_once_param<_Gp> __p(__f);
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
}
}
#else // _LIBCPP_CXX03_LANG
template <class _Callable>
inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable& __func) {
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
__call_once_param<_Callable> __p(__func);
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
}
}
template <class _Callable>
inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, const _Callable& __func) {
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
__call_once_param<const _Callable> __p(__func);
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
}
}
#endif // _LIBCPP_CXX03_LANG
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___MUTEX_ONCE_FLAG_H
|