aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/cxxsupp/libcxx/src/call_once.cpp
diff options
context:
space:
mode:
authormikhnenko <mikhnenko@yandex-team.com>2024-12-05 10:49:03 +0300
committermikhnenko <mikhnenko@yandex-team.com>2024-12-05 11:21:12 +0300
commit681668b400e84754eb7acbc0e173491bb4dfc8b2 (patch)
treee809b0abb22e9c506c032e256effebcf9ea88dbd /contrib/libs/cxxsupp/libcxx/src/call_once.cpp
parentfe60cde3cf1989964159845c2929a65056a8dcf3 (diff)
downloadydb-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.cpp89
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