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