Skip to content

Commit

Permalink
[libc++] Move once_flag outside of <mutex>
Browse files Browse the repository at this point in the history
This allows including once_flag directly from <__locale> instead of
depending on all of <mutex>, which requires threading. In turn, this
makes it easier to support locales on platforms without threading.

Drive-by change: clang-format once_flag.h and use _LIBCPP_HIDE_FROM_ABI

Differential Revision: https://reviews.llvm.org/D155487
  • Loading branch information
ldionne committed Aug 31, 2023
1 parent 1664eb0 commit c01794e
Show file tree
Hide file tree
Showing 17 changed files with 216 additions and 162 deletions.
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Expand Up @@ -543,6 +543,7 @@ set(files
__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
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__locale
Expand Up @@ -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 <cctype>
#include <clocale>
#include <cstdint>
#include <cstdlib>
#include <mutex>
#include <string>

// Some platforms require more includes than others. Keep the includes on all plaforms for now.
Expand Down
150 changes: 150 additions & 0 deletions 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 <cstdint>
#ifndef _LIBCPP_CXX03_LANG
# include <tuple>
#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 <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_(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 <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...>) {
_VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::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::_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 <class _Callable>
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 <class _Callable>
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<const _Callable> __p(__func);
std::__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
}
}

#endif // _LIBCPP_CXX03_LANG

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___MUTEX_ONCE_FLAG_H
1 change: 1 addition & 0 deletions libcxx/include/codecvt
Expand Up @@ -562,6 +562,7 @@ _LIBCPP_END_NAMESPACE_STD
# include <initializer_list>
# include <iosfwd>
# include <limits>
# include <mutex>
# include <new>
# include <stdexcept>
# include <type_traits>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/fstream
Expand Up @@ -1752,6 +1752,7 @@ _LIBCPP_POP_MACROS
# include <cstdlib>
# include <iosfwd>
# include <limits>
# include <mutex>
# include <new>
# include <stdexcept>
# include <type_traits>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/ios
Expand Up @@ -1055,6 +1055,7 @@ _LIBCPP_END_NAMESPACE_STD
# include <cstring>
# include <initializer_list>
# include <limits>
# include <mutex>
# include <new>
# include <stdexcept>
# include <system_error>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/locale
Expand Up @@ -4355,6 +4355,7 @@ _LIBCPP_POP_MACROS
# include <concepts>
# include <cstdarg>
# include <iterator>
# include <mutex>
# include <stdexcept>
# include <type_traits>
# include <typeinfo>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap.in
Expand Up @@ -1575,6 +1575,7 @@ module std_private_memory_resource_unsynchronized_pool_resource [system] { heade

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" }

Expand Down
152 changes: 1 addition & 151 deletions libcxx/include/mutex
Expand Up @@ -194,6 +194,7 @@ template<class Callable, class ...Args>
#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>
Expand Down Expand Up @@ -555,157 +556,6 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
#endif // _LIBCPP_STD_VER >= 17
#endif // !_LIBCPP_HAS_NO_THREADS

struct _LIBCPP_TEMPLATE_VIS once_flag;

#ifndef _LIBCPP_CXX03_LANG

template<class _Callable, class... _Args>
_LIBCPP_INLINE_VISIBILITY
void call_once(once_flag&, _Callable&&, _Args&&...);

#else // _LIBCPP_CXX03_LANG

template<class _Callable>
_LIBCPP_INLINE_VISIBILITY
void call_once(once_flag&, _Callable&);

template<class _Callable>
_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<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_INLINE_VISIBILITY
explicit __call_once_param(_Fp& __f) : __f_(__f) {}

_LIBCPP_INLINE_VISIBILITY
void operator()()
{
typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
__execute(_Index());
}

private:
template <size_t ..._Indices>
_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 _Fp>
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 <class _Fp>
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<class _Callable, class... _Args>
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<class _Callable>
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<class _Callable>
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<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
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/regex
Expand Up @@ -6953,6 +6953,7 @@ _LIBCPP_POP_MACROS
# include <cstdlib>
# include <iosfwd>
# include <iterator>
# include <mutex>
# include <new>
# include <type_traits>
# include <typeinfo>
Expand Down

0 comments on commit c01794e

Please sign in to comment.