看了下源代码,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 ?
