看了下源代码,call_once 的实现是
template<class _Callable, class... _Args>
inline _LIBCPP_INLINE_VISIBILITY
void
call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
{
if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
{
typedef tuple<_Callable&&, _Args&&...> _Gp;
_Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
__call_once_param<_Gp> __p(__f);
__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
}
}
其中__call_once简化后:
void __call_once(volatile once_flag::_State_type& flag, void* arg,
void (*func)(void*)) {
__libcpp_mutex_lock(&mut);
while (flag == 1)
__libcpp_condvar_wait(&cv, &mut);
if (flag == 0) {
try {
__libcpp_relaxed_store(&flag, once_flag::_State_type(1));
__libcpp_mutex_unlock(&mut);
func(arg);
__libcpp_mutex_lock(&mut);
__libcpp_atomic_store(&flag, ~once_flag::_State_type(0), _AO_Release);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
} catch (...) {
__libcpp_mutex_lock(&mut);
__libcpp_relaxed_store(&flag, once_flag::_State_type(0));
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
throw;
}
} else
__libcpp_mutex_unlock(&mut);
}
请问这里是出于什么考量不使用 atomic test_and_set ?