Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/c++/v1/__cxx03/semaphore is written in an unsupported language. File is not indexed.

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CXX03_SEMAPHORE
0011 #define _LIBCPP___CXX03_SEMAPHORE
0012 
0013 /*
0014     semaphore synopsis
0015 
0016 namespace std {
0017 
0018 template<ptrdiff_t least_max_value = implementation-defined>
0019 class counting_semaphore
0020 {
0021 public:
0022 static constexpr ptrdiff_t max() noexcept;
0023 
0024 constexpr explicit counting_semaphore(ptrdiff_t desired);
0025 ~counting_semaphore();
0026 
0027 counting_semaphore(const counting_semaphore&) = delete;
0028 counting_semaphore& operator=(const counting_semaphore&) = delete;
0029 
0030 void release(ptrdiff_t update = 1);
0031 void acquire();
0032 bool try_acquire() noexcept;
0033 template<class Rep, class Period>
0034     bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time);
0035 template<class Clock, class Duration>
0036     bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time);
0037 
0038 private:
0039 ptrdiff_t counter; // exposition only
0040 };
0041 
0042 using binary_semaphore = counting_semaphore<1>;
0043 
0044 }
0045 
0046 */
0047 
0048 #include <__cxx03/__config>
0049 
0050 #if !defined(_LIBCPP_HAS_NO_THREADS)
0051 
0052 #  include <__cxx03/__assert>
0053 #  include <__cxx03/__atomic/atomic_base.h>
0054 #  include <__cxx03/__atomic/atomic_sync.h>
0055 #  include <__cxx03/__atomic/memory_order.h>
0056 #  include <__cxx03/__chrono/time_point.h>
0057 #  include <__cxx03/__thread/poll_with_backoff.h>
0058 #  include <__cxx03/__thread/support.h>
0059 #  include <__cxx03/__thread/timed_backoff_policy.h>
0060 #  include <__cxx03/cstddef>
0061 #  include <__cxx03/limits>
0062 #  include <__cxx03/version>
0063 
0064 #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0065 #    pragma GCC system_header
0066 #  endif
0067 
0068 _LIBCPP_PUSH_MACROS
0069 #  include <__cxx03/__undef_macros>
0070 
0071 #  if _LIBCPP_STD_VER >= 14
0072 
0073 _LIBCPP_BEGIN_NAMESPACE_STD
0074 
0075 /*
0076 
0077 __atomic_semaphore_base is the general-case implementation.
0078 It is a typical Dijkstra semaphore algorithm over atomics, wait and notify
0079 functions. It avoids contention against users' own use of those facilities.
0080 
0081 */
0082 
0083 #    define _LIBCPP_SEMAPHORE_MAX (numeric_limits<ptrdiff_t>::max())
0084 
0085 class __atomic_semaphore_base {
0086   __atomic_base<ptrdiff_t> __a_;
0087 
0088 public:
0089   _LIBCPP_HIDE_FROM_ABI constexpr explicit __atomic_semaphore_base(ptrdiff_t __count) : __a_(__count) {}
0090   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void release(ptrdiff_t __update = 1) {
0091     auto __old = __a_.fetch_add(__update, memory_order_release);
0092     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0093         __update <= _LIBCPP_SEMAPHORE_MAX - __old, "update is greater than the expected value");
0094     if (__old == 0) {
0095       __a_.notify_all();
0096     }
0097   }
0098   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void acquire() {
0099     std::__atomic_wait_unless(
0100         __a_, [this](ptrdiff_t& __old) { return __try_acquire_impl(__old); }, memory_order_relaxed);
0101   }
0102   template <class _Rep, class _Period>
0103   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
0104   try_acquire_for(chrono::duration<_Rep, _Period> const& __rel_time) {
0105     if (__rel_time == chrono::duration<_Rep, _Period>::zero())
0106       return try_acquire();
0107     auto const __poll_fn = [this]() { return try_acquire(); };
0108     return std::__libcpp_thread_poll_with_backoff(__poll_fn, __libcpp_timed_backoff_policy(), __rel_time);
0109   }
0110   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool try_acquire() {
0111     auto __old = __a_.load(memory_order_relaxed);
0112     return __try_acquire_impl(__old);
0113   }
0114 
0115 private:
0116   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool __try_acquire_impl(ptrdiff_t& __old) {
0117     while (true) {
0118       if (__old == 0)
0119         return false;
0120       if (__a_.compare_exchange_weak(__old, __old - 1, memory_order_acquire, memory_order_relaxed))
0121         return true;
0122     }
0123   }
0124 };
0125 
0126 template <ptrdiff_t __least_max_value = _LIBCPP_SEMAPHORE_MAX>
0127 class _LIBCPP_DEPRECATED_ATOMIC_SYNC counting_semaphore {
0128   __atomic_semaphore_base __semaphore_;
0129 
0130 public:
0131   static_assert(__least_max_value >= 0, "The least maximum value must be a positive number");
0132 
0133   static constexpr ptrdiff_t max() noexcept { return __least_max_value; }
0134 
0135   _LIBCPP_HIDE_FROM_ABI constexpr explicit counting_semaphore(ptrdiff_t __count) : __semaphore_(__count) {
0136     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0137         __count >= 0,
0138         "counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be "
0139         "initialized with a negative value");
0140     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0141         __count <= max(),
0142         "counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be "
0143         "initialized with a value greater than max()");
0144   }
0145   ~counting_semaphore() = default;
0146 
0147   counting_semaphore(const counting_semaphore&)            = delete;
0148   counting_semaphore& operator=(const counting_semaphore&) = delete;
0149 
0150   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void release(ptrdiff_t __update = 1) {
0151     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "counting_semaphore:release called with a negative value");
0152     __semaphore_.release(__update);
0153   }
0154   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void acquire() { __semaphore_.acquire(); }
0155   template <class _Rep, class _Period>
0156   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
0157   try_acquire_for(chrono::duration<_Rep, _Period> const& __rel_time) {
0158     return __semaphore_.try_acquire_for(chrono::duration_cast<chrono::nanoseconds>(__rel_time));
0159   }
0160   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool try_acquire() { return __semaphore_.try_acquire(); }
0161   template <class _Clock, class _Duration>
0162   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
0163   try_acquire_until(chrono::time_point<_Clock, _Duration> const& __abs_time) {
0164     auto const __current = _Clock::now();
0165     if (__current >= __abs_time)
0166       return try_acquire();
0167     else
0168       return try_acquire_for(__abs_time - __current);
0169   }
0170 };
0171 
0172 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0173 using binary_semaphore _LIBCPP_DEPRECATED_ATOMIC_SYNC = counting_semaphore<1>;
0174 _LIBCPP_SUPPRESS_DEPRECATED_POP
0175 
0176 _LIBCPP_END_NAMESPACE_STD
0177 
0178 #  endif // _LIBCPP_STD_VER >= 14
0179 
0180 _LIBCPP_POP_MACROS
0181 
0182 #endif // !defined(_LIBCPP_HAS_NO_THREADS)
0183 
0184 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
0185 #  include <__cxx03/atomic>
0186 #endif
0187 
0188 #endif //_LIBCPP___CXX03_SEMAPHORE