Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/c++/v1/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_SEMAPHORE
0011 #define _LIBCPP_SEMAPHORE
0012 
0013 /*
0014     semaphore synopsis
0015 
0016 namespace std {
0017 
0018 template<ptrdiff_t least_max_value = implementation-defined>
0019 class counting_semaphore                          // since C++20
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>; // since C++20
0043 
0044 }
0045 
0046 */
0047 
0048 #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
0049 #  include <__cxx03/semaphore>
0050 #else
0051 #  include <__config>
0052 
0053 #  if _LIBCPP_HAS_THREADS
0054 
0055 #    include <__assert>
0056 #    include <__atomic/atomic.h>
0057 #    include <__atomic/atomic_sync.h>
0058 #    include <__atomic/memory_order.h>
0059 #    include <__chrono/time_point.h>
0060 #    include <__cstddef/ptrdiff_t.h>
0061 #    include <__thread/poll_with_backoff.h>
0062 #    include <__thread/support.h>
0063 #    include <__thread/timed_backoff_policy.h>
0064 #    include <limits>
0065 #    include <version>
0066 
0067 #    if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0068 #      pragma GCC system_header
0069 #    endif
0070 
0071 _LIBCPP_PUSH_MACROS
0072 #    include <__undef_macros>
0073 
0074 #    if _LIBCPP_STD_VER >= 20
0075 
0076 _LIBCPP_BEGIN_NAMESPACE_STD
0077 
0078 /*
0079 
0080 __atomic_semaphore_base is the general-case implementation.
0081 It is a typical Dijkstra semaphore algorithm over atomics, wait and notify
0082 functions. It avoids contention against users' own use of those facilities.
0083 
0084 */
0085 
0086 #      define _LIBCPP_SEMAPHORE_MAX (numeric_limits<ptrdiff_t>::max())
0087 
0088 class __atomic_semaphore_base {
0089   atomic<ptrdiff_t> __a_;
0090 
0091 public:
0092   _LIBCPP_HIDE_FROM_ABI constexpr explicit __atomic_semaphore_base(ptrdiff_t __count) : __a_(__count) {}
0093   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void release(ptrdiff_t __update = 1) {
0094     auto __old = __a_.fetch_add(__update, memory_order_release);
0095     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0096         __update <= _LIBCPP_SEMAPHORE_MAX - __old, "update is greater than the expected value");
0097     if (__old == 0) {
0098       __a_.notify_all();
0099     }
0100   }
0101   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void acquire() {
0102     std::__atomic_wait_unless(__a_, memory_order_relaxed, [this](ptrdiff_t& __old) {
0103       return __try_acquire_impl(__old);
0104     });
0105   }
0106   template <class _Rep, class _Period>
0107   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
0108   try_acquire_for(chrono::duration<_Rep, _Period> const& __rel_time) {
0109     if (__rel_time == chrono::duration<_Rep, _Period>::zero())
0110       return try_acquire();
0111     auto const __poll_fn = [this]() { return try_acquire(); };
0112     return std::__libcpp_thread_poll_with_backoff(__poll_fn, __libcpp_timed_backoff_policy(), __rel_time);
0113   }
0114   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool try_acquire() {
0115     auto __old = __a_.load(memory_order_relaxed);
0116     return __try_acquire_impl(__old);
0117   }
0118 
0119 private:
0120   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool __try_acquire_impl(ptrdiff_t& __old) {
0121     while (true) {
0122       if (__old == 0)
0123         return false;
0124       if (__a_.compare_exchange_weak(__old, __old - 1, memory_order_acquire, memory_order_relaxed))
0125         return true;
0126     }
0127   }
0128 };
0129 
0130 template <ptrdiff_t __least_max_value = _LIBCPP_SEMAPHORE_MAX>
0131 class counting_semaphore {
0132   __atomic_semaphore_base __semaphore_;
0133 
0134 public:
0135   static_assert(__least_max_value >= 0, "The least maximum value must be a positive number");
0136 
0137   static constexpr ptrdiff_t max() noexcept { return __least_max_value; }
0138 
0139   _LIBCPP_HIDE_FROM_ABI constexpr explicit counting_semaphore(ptrdiff_t __count) : __semaphore_(__count) {
0140     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0141         __count >= 0,
0142         "counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be "
0143         "initialized with a negative value");
0144     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0145         __count <= max(),
0146         "counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be "
0147         "initialized with a value greater than max()");
0148   }
0149   ~counting_semaphore() = default;
0150 
0151   counting_semaphore(const counting_semaphore&)            = delete;
0152   counting_semaphore& operator=(const counting_semaphore&) = delete;
0153 
0154   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void release(ptrdiff_t __update = 1) {
0155     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "counting_semaphore:release called with a negative value");
0156     __semaphore_.release(__update);
0157   }
0158   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void acquire() { __semaphore_.acquire(); }
0159   template <class _Rep, class _Period>
0160   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
0161   try_acquire_for(chrono::duration<_Rep, _Period> const& __rel_time) {
0162     return __semaphore_.try_acquire_for(chrono::duration_cast<chrono::nanoseconds>(__rel_time));
0163   }
0164   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool try_acquire() { return __semaphore_.try_acquire(); }
0165   template <class _Clock, class _Duration>
0166   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
0167   try_acquire_until(chrono::time_point<_Clock, _Duration> const& __abs_time) {
0168     auto const __current = _Clock::now();
0169     if (__current >= __abs_time)
0170       return try_acquire();
0171     else
0172       return try_acquire_for(__abs_time - __current);
0173   }
0174 };
0175 
0176 using binary_semaphore = counting_semaphore<1>;
0177 
0178 _LIBCPP_END_NAMESPACE_STD
0179 
0180 #    endif // _LIBCPP_STD_VER >= 20
0181 
0182 _LIBCPP_POP_MACROS
0183 
0184 #  endif // _LIBCPP_HAS_THREADS
0185 
0186 #  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
0187 #    include <atomic>
0188 #    include <cstddef>
0189 #  endif
0190 #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
0191 
0192 #endif // _LIBCPP_SEMAPHORE