Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions libcxx/include/__mutex/once_flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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_;

Expand Down Expand Up @@ -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);
Expand All @@ -129,15 +133,15 @@ 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>);
}
}

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>);
}
Expand Down
18 changes: 9 additions & 9 deletions libcxx/src/mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down