[libc++][NFC] Clean up std::__call_once

__call_once is large and cluttered with #ifdef preprocessor guards. This
cleans it up a bit by using an exception guard instead of try-catch.

Differential Revision: https://reviews.llvm.org/D112319
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
This commit is contained in:
Daniel McIntosh 2023-09-13 16:57:13 -04:00 committed by Louis Dionne
parent 641124a9b9
commit be8c2df2b1

View File

@ -8,6 +8,7 @@
#include <__assert> #include <__assert>
#include <__thread/id.h> #include <__thread/id.h>
#include <__utility/exception_guard.h>
#include <limits> #include <limits>
#include <mutex> #include <mutex>
@ -205,56 +206,40 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg,
void (*func)(void*)) void (*func)(void*))
{ {
#if defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_NO_THREADS)
if (flag == once_flag::_Unset)
{ if (flag == once_flag::_Unset) {
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS auto guard = std::__make_exception_guard([&flag] { flag = once_flag::_Unset; });
try flag = once_flag::_Pending;
{ func(arg);
#endif // _LIBCPP_HAS_NO_EXCEPTIONS flag = once_flag::_Complete;
flag = once_flag::_Pending; guard.__complete();
func(arg);
flag = once_flag::_Complete;
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
}
catch (...)
{
flag = once_flag::_Unset;
throw;
}
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
} }
#else // !_LIBCPP_HAS_NO_THREADS #else // !_LIBCPP_HAS_NO_THREADS
__libcpp_mutex_lock(&mut); __libcpp_mutex_lock(&mut);
while (flag == once_flag::_Pending) while (flag == once_flag::_Pending)
__libcpp_condvar_wait(&cv, &mut); __libcpp_condvar_wait(&cv, &mut);
if (flag == once_flag::_Unset) if (flag == once_flag::_Unset) {
{ auto guard = std::__make_exception_guard([&flag] {
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
__libcpp_relaxed_store(&flag, once_flag::_Pending);
__libcpp_mutex_unlock(&mut);
func(arg);
__libcpp_mutex_lock(&mut);
__libcpp_atomic_store(&flag, once_flag::_Complete,
_AO_Release);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
}
catch (...)
{
__libcpp_mutex_lock(&mut); __libcpp_mutex_lock(&mut);
__libcpp_relaxed_store(&flag, once_flag::_Unset); __libcpp_relaxed_store(&flag, once_flag::_Unset);
__libcpp_mutex_unlock(&mut); __libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv); __libcpp_condvar_broadcast(&cv);
throw; });
}
#endif // _LIBCPP_HAS_NO_EXCEPTIONS __libcpp_relaxed_store(&flag, once_flag::_Pending);
}
else
__libcpp_mutex_unlock(&mut); __libcpp_mutex_unlock(&mut);
func(arg);
__libcpp_mutex_lock(&mut);
__libcpp_atomic_store(&flag, once_flag::_Complete, _AO_Release);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
guard.__complete();
} else {
__libcpp_mutex_unlock(&mut);
}
#endif // !_LIBCPP_HAS_NO_THREADS #endif // !_LIBCPP_HAS_NO_THREADS
} }