[libc++][NFC] Introduce named states in std::call_once (#66289)

This idea is extracted from https://reviews.llvm.org/D112319. It makes
the code easier to read but doesn't otherwise change any functionality.
This commit is contained in:
Louis Dionne 2023-09-15 10:14:13 -04:00 committed by GitHub
parent de6a919f77
commit fdf91c768e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 13 deletions

View File

@ -45,7 +45,7 @@ _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) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR once_flag() _NOEXCEPT : __state_(_Unset) {}
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
@ -55,6 +55,10 @@ struct _LIBCPP_TEMPLATE_VIS once_flag {
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_;
@ -117,7 +121,7 @@ _LIBCPP_EXPORTED_FROM_ABI void __call_once(volatile once_flag::_State_type&, voi
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)) {
if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {
typedef tuple<_Callable&&, _Args&&...> _Gp;
_Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
__call_once_param<_Gp> __p(__f);
@ -129,7 +133,7 @@ inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable&& __fun
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)) {
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>);
}
@ -137,7 +141,7 @@ inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable& __func
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)) {
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>);
}

View File

@ -205,39 +205,39 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg,
void (*func)(void*))
{
#if defined(_LIBCPP_HAS_NO_THREADS)
if (flag == 0)
if (flag == once_flag::_Unset)
{
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
flag = 1;
flag = once_flag::_Pending;
func(arg);
flag = ~once_flag::_State_type(0);
flag = once_flag::_Complete;
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
}
catch (...)
{
flag = 0;
flag = once_flag::_Unset;
throw;
}
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
}
#else // !_LIBCPP_HAS_NO_THREADS
__libcpp_mutex_lock(&mut);
while (flag == 1)
while (flag == once_flag::_Pending)
__libcpp_condvar_wait(&cv, &mut);
if (flag == 0)
if (flag == once_flag::_Unset)
{
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
__libcpp_relaxed_store(&flag, once_flag::_State_type(1));
__libcpp_relaxed_store(&flag, once_flag::_Pending);
__libcpp_mutex_unlock(&mut);
func(arg);
__libcpp_mutex_lock(&mut);
__libcpp_atomic_store(&flag, ~once_flag::_State_type(0),
__libcpp_atomic_store(&flag, once_flag::_Complete,
_AO_Release);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
@ -246,7 +246,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg,
catch (...)
{
__libcpp_mutex_lock(&mut);
__libcpp_relaxed_store(&flag, once_flag::_State_type(0));
__libcpp_relaxed_store(&flag, once_flag::_Unset);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
throw;