diff options
author | mikhnenko <mikhnenko@yandex-team.com> | 2024-12-05 10:49:03 +0300 |
---|---|---|
committer | mikhnenko <mikhnenko@yandex-team.com> | 2024-12-05 11:21:12 +0300 |
commit | 681668b400e84754eb7acbc0e173491bb4dfc8b2 (patch) | |
tree | e809b0abb22e9c506c032e256effebcf9ea88dbd /contrib/libs/cxxsupp/libcxx/src/call_once.cpp | |
parent | fe60cde3cf1989964159845c2929a65056a8dcf3 (diff) | |
download | ydb-681668b400e84754eb7acbc0e173491bb4dfc8b2.tar.gz |
Update libcxx to 18 Dec 3b0705827dbe711788c6b6bec3afa94205db1ce8
commit_hash:875d8582c26b8bf016af25e00ad77d9bbf081948
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/src/call_once.cpp')
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/src/call_once.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/src/call_once.cpp b/contrib/libs/cxxsupp/libcxx/src/call_once.cpp new file mode 100644 index 0000000000..a4fb1c35f1 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/src/call_once.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__mutex/once_flag.h> +#include <__utility/exception_guard.h> + +#ifndef _LIBCPP_HAS_NO_THREADS +# include <__threading_support> +#endif + +#include "include/atomic_support.h" + +_LIBCPP_BEGIN_NAMESPACE_STD + +// If dispatch_once_f ever handles C++ exceptions, and if one can get to it +// without illegal macros (unexpected macros not beginning with _UpperCase or +// __lowercase), and if it stops spinning waiting threads, then call_once should +// call into dispatch_once_f instead of here. Relevant radar this code needs to +// keep in sync with: 7741191. + +#ifndef _LIBCPP_HAS_NO_THREADS +static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; +static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; +#endif + +#ifdef _LIBCPP_ABI_MICROSOFT +void __call_once(volatile std::atomic<once_flag::_State_type>& flag, void* arg, + void (*func)(void*)) +#else +void __call_once(volatile once_flag::_State_type& flag, void* arg, + void (*func)(void*)) +#endif +{ +#if defined(_LIBCPP_HAS_NO_THREADS) + + 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) { + auto guard = std::__make_exception_guard([&flag] { + __libcpp_mutex_lock(&mut); +#ifdef _LIBCPP_ABI_MICROSOFT + flag.store(once_flag::_Unset); +#else + __libcpp_relaxed_store(&flag, once_flag::_Unset); +#endif + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); + }); + +#ifdef _LIBCPP_ABI_MICROSOFT + flag.store(once_flag::_Pending, memory_order_relaxed); +#else + __libcpp_relaxed_store(&flag, once_flag::_Pending); +#endif + __libcpp_mutex_unlock(&mut); + func(arg); + __libcpp_mutex_lock(&mut); +#ifdef _LIBCPP_ABI_MICROSOFT + flag.store(once_flag::_Complete, memory_order_release); +#else + __libcpp_atomic_store(&flag, once_flag::_Complete, _AO_Release); +#endif + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); + guard.__complete(); + } else { + __libcpp_mutex_unlock(&mut); + } + +#endif // !_LIBCPP_HAS_NO_THREADS +} + +_LIBCPP_END_NAMESPACE_STD |