diff --git a/libcxx/src/mutex.cpp b/libcxx/src/mutex.cpp --- a/libcxx/src/mutex.cpp +++ b/libcxx/src/mutex.cpp @@ -8,6 +8,7 @@ #include <__assert> #include <__thread/id.h> +#include <__utility/exception_guard.h> #include #include @@ -205,56 +206,40 @@ 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 }