diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/cxxsupp/libcxx/include/semaphore | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/include/semaphore')
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/semaphore | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/include/semaphore b/contrib/libs/cxxsupp/libcxx/include/semaphore new file mode 100644 index 0000000000..4f9ecd0461 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/semaphore @@ -0,0 +1,240 @@ +// -*- C++ -*- +//===--------------------------- semaphore --------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_SEMAPHORE +#define _LIBCPP_SEMAPHORE + +/* + semaphore synopsis + +namespace std { + +template<ptrdiff_t least_max_value = implementation-defined> +class counting_semaphore +{ +public: +static constexpr ptrdiff_t max() noexcept; + +constexpr explicit counting_semaphore(ptrdiff_t desired); +~counting_semaphore(); + +counting_semaphore(const counting_semaphore&) = delete; +counting_semaphore& operator=(const counting_semaphore&) = delete; + +void release(ptrdiff_t update = 1); +void acquire(); +bool try_acquire() noexcept; +template<class Rep, class Period> + bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time); +template<class Clock, class Duration> + bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time); + +private: +ptrdiff_t counter; // exposition only +}; + +using binary_semaphore = counting_semaphore<1>; + +} + +*/ + +#include <__availability> +#include <__config> +#include <__threading_support> +#include <atomic> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#ifdef _LIBCPP_HAS_NO_THREADS +# error <semaphore> is not supported on this single threaded system +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 14 + +_LIBCPP_BEGIN_NAMESPACE_STD + +/* + +__atomic_semaphore_base is the general-case implementation, to be used for +user-requested least-max values that exceed the OS implementation support +(incl. when the OS has no support of its own) and for binary semaphores. + +It is a typical Dijkstra semaphore algorithm over atomics, wait and notify +functions. It avoids contention against users' own use of those facilities. + +*/ + +class __atomic_semaphore_base +{ + __atomic_base<ptrdiff_t> __a; + +public: + _LIBCPP_INLINE_VISIBILITY + constexpr explicit __atomic_semaphore_base(ptrdiff_t __count) : __a(__count) + { + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + void release(ptrdiff_t __update = 1) + { + if(0 < __a.fetch_add(__update, memory_order_release)) + ; + else if(__update > 1) + __a.notify_all(); + else + __a.notify_one(); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + void acquire() + { + auto const __test_fn = [this]() -> bool { + auto __old = __a.load(memory_order_relaxed); + return (__old != 0) && __a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed); + }; + __cxx_atomic_wait(&__a.__a_, __test_fn); + } + template <class Rep, class Period> + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) + { + auto const __test_fn = [this]() -> bool { + auto __old = __a.load(memory_order_acquire); + while(1) { + if (__old == 0) + return false; + if(__a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed)) + return true; + } + }; + return __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy(), __rel_time); + } +}; + +#ifndef _LIBCPP_NO_NATIVE_SEMAPHORES + +/* + +__platform_semaphore_base a simple wrapper for the OS semaphore type. That +is, every call is routed to the OS in the most direct manner possible. + +*/ + +class __platform_semaphore_base +{ + __libcpp_semaphore_t __semaphore; + +public: + _LIBCPP_INLINE_VISIBILITY + explicit __platform_semaphore_base(ptrdiff_t __count) : + __semaphore() + { + __libcpp_semaphore_init(&__semaphore, __count); + } + _LIBCPP_INLINE_VISIBILITY + ~__platform_semaphore_base() { + __libcpp_semaphore_destroy(&__semaphore); + } + _LIBCPP_INLINE_VISIBILITY + void release(ptrdiff_t __update) + { + for(; __update; --__update) + __libcpp_semaphore_post(&__semaphore); + } + _LIBCPP_INLINE_VISIBILITY + void acquire() + { + __libcpp_semaphore_wait(&__semaphore); + } + _LIBCPP_INLINE_VISIBILITY + bool try_acquire_for(chrono::nanoseconds __rel_time) + { + return __libcpp_semaphore_wait_timed(&__semaphore, __rel_time); + } +}; + +template<ptrdiff_t __least_max_value> +using __semaphore_base = + typename conditional<(__least_max_value > 1 && __least_max_value <= _LIBCPP_SEMAPHORE_MAX), + __platform_semaphore_base, + __atomic_semaphore_base>::type; + +#else + +template<ptrdiff_t __least_max_value> +using __semaphore_base = + __atomic_semaphore_base; + +#define _LIBCPP_SEMAPHORE_MAX (numeric_limits<ptrdiff_t>::max()) + +#endif //_LIBCPP_NO_NATIVE_SEMAPHORES + +template<ptrdiff_t __least_max_value = _LIBCPP_SEMAPHORE_MAX> +class counting_semaphore +{ + __semaphore_base<__least_max_value> __semaphore; + +public: + static constexpr ptrdiff_t max() noexcept { + return __least_max_value; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr explicit counting_semaphore(ptrdiff_t __count) : __semaphore(__count) { } + ~counting_semaphore() = default; + + counting_semaphore(const counting_semaphore&) = delete; + counting_semaphore& operator=(const counting_semaphore&) = delete; + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + void release(ptrdiff_t __update = 1) + { + __semaphore.release(__update); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + void acquire() + { + __semaphore.acquire(); + } + template<class Rep, class Period> + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) + { + return __semaphore.try_acquire_for(chrono::duration_cast<chrono::nanoseconds>(__rel_time)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + bool try_acquire() + { + return try_acquire_for(chrono::nanoseconds::zero()); + } + template <class Clock, class Duration> + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + bool try_acquire_until(chrono::time_point<Clock, Duration> const& __abs_time) + { + auto const current = Clock::now(); + if(current >= __abs_time) + return try_acquire(); + else + return try_acquire_for(__abs_time - current); + } +}; + +using binary_semaphore = counting_semaphore<1>; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 14 + +_LIBCPP_POP_MACROS + +#endif //_LIBCPP_SEMAPHORE |