diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -543,6 +543,7 @@ __memory_resource/unsynchronized_pool_resource.h __mutex/lock_guard.h __mutex/mutex.h + __mutex/once_flag.h __mutex/tag_types.h __mutex/unique_lock.h __node_handle diff --git a/libcxx/include/__locale b/libcxx/include/__locale --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -13,12 +13,12 @@ #include <__availability> #include <__config> #include <__memory/shared_ptr.h> // __shared_count +#include <__mutex/once_flag.h> #include <__type_traits/make_unsigned.h> #include #include #include #include -#include #include // Some platforms require more includes than others. Keep the includes on all plaforms for now. diff --git a/libcxx/include/__mutex/once_flag.h b/libcxx/include/__mutex/once_flag.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__mutex/once_flag.h @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#ifndef _LIBCPP_CXX03_LANG +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_TEMPLATE_VIS once_flag; + +#ifndef _LIBCPP_CXX03_LANG + +template +_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&&, _Args&&...); + +#else // _LIBCPP_CXX03_LANG + +template +_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&); + +template +_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_(0) {} + 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 + +private: + _State_type __state_; + +#ifndef _LIBCPP_CXX03_LANG + template + friend void call_once(once_flag&, _Callable&&, _Args&&...); +#else // _LIBCPP_CXX03_LANG + template + friend void call_once(once_flag&, _Callable&); + + template + friend void call_once(once_flag&, const _Callable&); +#endif // _LIBCPP_CXX03_LANG +}; + +#ifndef _LIBCPP_CXX03_LANG + +template +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::value, 1>::type _Index; + __execute(_Index()); + } + +private: + template + _LIBCPP_HIDE_FROM_ABI void __execute(__tuple_indices<_Indices...>) { + _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); + } +}; + +#else + +template +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 +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 +inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) { + if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) { + typedef tuple<_Callable&&, _Args&&...> _Gp; + _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); + __call_once_param<_Gp> __p(__f); + std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); + } +} + +#else // _LIBCPP_CXX03_LANG + +template +inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable& __func) { + if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) { + __call_once_param<_Callable> __p(__func); + std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); + } +} + +template +inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, const _Callable& __func) { + if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) { + __call_once_param __p(__func); + std::__call_once(__flag.__state_, &__p, &__call_once_proxy); + } +} + +#endif // _LIBCPP_CXX03_LANG + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MUTEX_ONCE_FLAG_H diff --git a/libcxx/include/codecvt b/libcxx/include/codecvt --- a/libcxx/include/codecvt +++ b/libcxx/include/codecvt @@ -562,6 +562,7 @@ # include # include # include +# include # include # include # include diff --git a/libcxx/include/fstream b/libcxx/include/fstream --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -1752,6 +1752,7 @@ # include # include # include +# include # include # include # include diff --git a/libcxx/include/ios b/libcxx/include/ios --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -1055,6 +1055,7 @@ # include # include # include +# include # include # include # include diff --git a/libcxx/include/locale b/libcxx/include/locale --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -4355,6 +4355,7 @@ # include # include # include +# include # include # include # include diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1575,6 +1575,7 @@ module std_private_mutex_lock_guard [system] { header "__mutex/lock_guard.h" } module std_private_mutex_mutex [system] { header "__mutex/mutex.h" } +module std_private_mutex_once_flag [system] { header "__mutex/once_flag.h" } module std_private_mutex_tag_types [system] { header "__mutex/tag_types.h" } module std_private_mutex_unique_lock [system] { header "__mutex/unique_lock.h" } diff --git a/libcxx/include/mutex b/libcxx/include/mutex --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -194,6 +194,7 @@ #include <__memory/shared_ptr.h> #include <__mutex/lock_guard.h> #include <__mutex/mutex.h> +#include <__mutex/once_flag.h> #include <__mutex/tag_types.h> #include <__mutex/unique_lock.h> #include <__thread/id.h> @@ -555,157 +556,6 @@ #endif // _LIBCPP_STD_VER >= 17 #endif // !_LIBCPP_HAS_NO_THREADS -struct _LIBCPP_TEMPLATE_VIS once_flag; - -#ifndef _LIBCPP_CXX03_LANG - -template -_LIBCPP_INLINE_VISIBILITY -void call_once(once_flag&, _Callable&&, _Args&&...); - -#else // _LIBCPP_CXX03_LANG - -template -_LIBCPP_INLINE_VISIBILITY -void call_once(once_flag&, _Callable&); - -template -_LIBCPP_INLINE_VISIBILITY -void call_once(once_flag&, const _Callable&); - -#endif // _LIBCPP_CXX03_LANG - -struct _LIBCPP_TEMPLATE_VIS once_flag -{ - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR - once_flag() _NOEXCEPT : __state_(0) {} - 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 - -private: - _State_type __state_; - -#ifndef _LIBCPP_CXX03_LANG - template - friend - void call_once(once_flag&, _Callable&&, _Args&&...); -#else // _LIBCPP_CXX03_LANG - template - friend - void call_once(once_flag&, _Callable&); - - template - friend - void call_once(once_flag&, const _Callable&); -#endif // _LIBCPP_CXX03_LANG -}; - -#ifndef _LIBCPP_CXX03_LANG - -template -class __call_once_param -{ - _Fp& __f_; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __call_once_param(_Fp& __f) : __f_(__f) {} - - _LIBCPP_INLINE_VISIBILITY - void operator()() - { - typedef typename __make_tuple_indices::value, 1>::type _Index; - __execute(_Index()); - } - -private: - template - _LIBCPP_INLINE_VISIBILITY - void __execute(__tuple_indices<_Indices...>) - { - _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); - } -}; - -#else - -template -class __call_once_param -{ - _Fp& __f_; -public: - _LIBCPP_INLINE_VISIBILITY - explicit __call_once_param(_Fp& __f) : __f_(__f) {} - - _LIBCPP_INLINE_VISIBILITY - void operator()() - { - __f_(); - } -}; - -#endif - -template -void _LIBCPP_INLINE_VISIBILITY -__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 -inline _LIBCPP_INLINE_VISIBILITY -void -call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) -{ - if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) - { - typedef tuple<_Callable&&, _Args&&...> _Gp; - _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); - __call_once_param<_Gp> __p(__f); - std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); - } -} - -#else // _LIBCPP_CXX03_LANG - -template -inline _LIBCPP_INLINE_VISIBILITY -void -call_once(once_flag& __flag, _Callable& __func) -{ - if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) - { - __call_once_param<_Callable> __p(__func); - std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); - } -} - -template -inline _LIBCPP_INLINE_VISIBILITY -void -call_once(once_flag& __flag, const _Callable& __func) -{ - if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) - { - __call_once_param __p(__func); - std::__call_once(__flag.__state_, &__p, &__call_once_proxy); - } -} - -#endif // _LIBCPP_CXX03_LANG - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/regex b/libcxx/include/regex --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -6957,6 +6957,7 @@ # include # include # include +# include # include # include # include