Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:26

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___CXX03___CONDITION_VARIABLE_CONDITION_VARIABLE_H
0010 #define _LIBCPP___CXX03___CONDITION_VARIABLE_CONDITION_VARIABLE_H
0011 
0012 #include <__cxx03/__chrono/duration.h>
0013 #include <__cxx03/__chrono/steady_clock.h>
0014 #include <__cxx03/__chrono/system_clock.h>
0015 #include <__cxx03/__chrono/time_point.h>
0016 #include <__cxx03/__config>
0017 #include <__cxx03/__mutex/mutex.h>
0018 #include <__cxx03/__mutex/unique_lock.h>
0019 #include <__cxx03/__system_error/system_error.h>
0020 #include <__cxx03/__thread/support.h>
0021 #include <__cxx03/__type_traits/enable_if.h>
0022 #include <__cxx03/__type_traits/is_floating_point.h>
0023 #include <__cxx03/__utility/move.h>
0024 #include <__cxx03/limits>
0025 #include <__cxx03/ratio>
0026 
0027 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0028 #  pragma GCC system_header
0029 #endif
0030 
0031 _LIBCPP_PUSH_MACROS
0032 #include <__cxx03/__undef_macros>
0033 
0034 _LIBCPP_BEGIN_NAMESPACE_STD
0035 
0036 #ifndef _LIBCPP_HAS_NO_THREADS
0037 
0038 // enum class cv_status
0039 _LIBCPP_DECLARE_STRONG_ENUM(cv_status){no_timeout, timeout};
0040 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
0041 
0042 class _LIBCPP_EXPORTED_FROM_ABI condition_variable {
0043   __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
0044 
0045 public:
0046   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
0047 
0048 #  ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
0049   ~condition_variable() = default;
0050 #  else
0051   ~condition_variable();
0052 #  endif
0053 
0054   condition_variable(const condition_variable&)            = delete;
0055   condition_variable& operator=(const condition_variable&) = delete;
0056 
0057   void notify_one() _NOEXCEPT;
0058   void notify_all() _NOEXCEPT;
0059 
0060   void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
0061   template <class _Predicate>
0062   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(unique_lock<mutex>& __lk, _Predicate __pred);
0063 
0064   template <class _Clock, class _Duration>
0065   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
0066   wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t);
0067 
0068   template <class _Clock, class _Duration, class _Predicate>
0069   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
0070   wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred);
0071 
0072   template <class _Rep, class _Period>
0073   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
0074   wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d);
0075 
0076   template <class _Rep, class _Period, class _Predicate>
0077   bool _LIBCPP_HIDE_FROM_ABI
0078   wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
0079 
0080   typedef __libcpp_condvar_t* native_handle_type;
0081   _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; }
0082 
0083 private:
0084   void
0085   __do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
0086 #  if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
0087   _LIBCPP_HIDE_FROM_ABI void
0088   __do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
0089 #  endif
0090   template <class _Clock>
0091   _LIBCPP_HIDE_FROM_ABI void
0092   __do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
0093 };
0094 #endif // !_LIBCPP_HAS_NO_THREADS
0095 
0096 template <class _Rep, class _Period, __enable_if_t<is_floating_point<_Rep>::value, int> = 0>
0097 inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) {
0098   using namespace chrono;
0099   using __ratio       = ratio_divide<_Period, nano>;
0100   using __ns_rep      = nanoseconds::rep;
0101   _Rep __result_float = __d.count() * __ratio::num / __ratio::den;
0102 
0103   _Rep __result_max = numeric_limits<__ns_rep>::max();
0104   if (__result_float >= __result_max) {
0105     return nanoseconds::max();
0106   }
0107 
0108   _Rep __result_min = numeric_limits<__ns_rep>::min();
0109   if (__result_float <= __result_min) {
0110     return nanoseconds::min();
0111   }
0112 
0113   return nanoseconds(static_cast<__ns_rep>(__result_float));
0114 }
0115 
0116 template <class _Rep, class _Period, __enable_if_t<!is_floating_point<_Rep>::value, int> = 0>
0117 inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) {
0118   using namespace chrono;
0119   if (__d.count() == 0) {
0120     return nanoseconds(0);
0121   }
0122 
0123   using __ratio         = ratio_divide<_Period, nano>;
0124   using __ns_rep        = nanoseconds::rep;
0125   __ns_rep __result_max = numeric_limits<__ns_rep>::max();
0126   if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) {
0127     return nanoseconds::max();
0128   }
0129 
0130   __ns_rep __result_min = numeric_limits<__ns_rep>::min();
0131   if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) {
0132     return nanoseconds::min();
0133   }
0134 
0135   __ns_rep __result = __d.count() * __ratio::num / __ratio::den;
0136   if (__result == 0) {
0137     return nanoseconds(1);
0138   }
0139 
0140   return nanoseconds(__result);
0141 }
0142 
0143 #ifndef _LIBCPP_HAS_NO_THREADS
0144 template <class _Predicate>
0145 void condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) {
0146   while (!__pred())
0147     wait(__lk);
0148 }
0149 
0150 template <class _Clock, class _Duration>
0151 cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
0152   using namespace chrono;
0153   using __clock_tp_ns = time_point<_Clock, nanoseconds>;
0154 
0155   typename _Clock::time_point __now = _Clock::now();
0156   if (__t <= __now)
0157     return cv_status::timeout;
0158 
0159   __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch()));
0160 
0161   __do_timed_wait(__lk, __t_ns);
0162   return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
0163 }
0164 
0165 template <class _Clock, class _Duration, class _Predicate>
0166 bool condition_variable::wait_until(
0167     unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
0168   while (!__pred()) {
0169     if (wait_until(__lk, __t) == cv_status::timeout)
0170       return __pred();
0171   }
0172   return true;
0173 }
0174 
0175 template <class _Rep, class _Period>
0176 cv_status condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) {
0177   using namespace chrono;
0178   if (__d <= __d.zero())
0179     return cv_status::timeout;
0180   using __ns_rep                   = nanoseconds::rep;
0181   steady_clock::time_point __c_now = steady_clock::now();
0182 
0183 #  if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
0184   using __clock_tp_ns     = time_point<steady_clock, nanoseconds>;
0185   __ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count();
0186 #  else
0187   using __clock_tp_ns     = time_point<system_clock, nanoseconds>;
0188   __ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
0189 #  endif
0190 
0191   __ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count();
0192 
0193   if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
0194     __do_timed_wait(__lk, __clock_tp_ns::max());
0195   } else {
0196     __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
0197   }
0198 
0199   return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout;
0200 }
0201 
0202 template <class _Rep, class _Period, class _Predicate>
0203 inline bool
0204 condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) {
0205   return wait_until(__lk, chrono::steady_clock::now() + __d, std::move(__pred));
0206 }
0207 
0208 #  if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
0209 inline void condition_variable::__do_timed_wait(
0210     unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT {
0211   using namespace chrono;
0212   if (!__lk.owns_lock())
0213     __throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked");
0214   nanoseconds __d = __tp.time_since_epoch();
0215   timespec __ts;
0216   seconds __s                 = duration_cast<seconds>(__d);
0217   using __ts_sec              = decltype(__ts.tv_sec);
0218   const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
0219   if (__s.count() < __ts_sec_max) {
0220     __ts.tv_sec  = static_cast<__ts_sec>(__s.count());
0221     __ts.tv_nsec = (__d - __s).count();
0222   } else {
0223     __ts.tv_sec  = __ts_sec_max;
0224     __ts.tv_nsec = giga::num - 1;
0225   }
0226   int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
0227   if (__ec != 0 && __ec != ETIMEDOUT)
0228     __throw_system_error(__ec, "condition_variable timed_wait failed");
0229 }
0230 #  endif // _LIBCPP_HAS_COND_CLOCKWAIT
0231 
0232 template <class _Clock>
0233 inline void condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
0234                                                 chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT {
0235   wait_for(__lk, __tp - _Clock::now());
0236 }
0237 
0238 #endif // _LIBCPP_HAS_NO_THREADS
0239 
0240 _LIBCPP_END_NAMESPACE_STD
0241 
0242 _LIBCPP_POP_MACROS
0243 
0244 #endif // _LIBCPP___CXX03___CONDITION_VARIABLE_CONDITION_VARIABLE_H