95#include <condition_variable>
125 using native_handle_type = pthread_cond_t*;
144 void notify_one() noexcept;
149 void notify_all() noexcept;
156 void wait(std::unique_lock<std::mutex>& lock) noexcept;
165 template <typename PredicateT>
166 void wait(std::unique_lock<std::mutex>& lock, PredicateT p) noexcept;
177 template <typename DurationT>
178 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
179 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
193 template <typename DurationT>
194 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
195 const std::chrono::time_point<std::chrono::system_clock, DurationT>& atime) noexcept;
210 template <typename ClockT, typename DurationT>
211 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
212 const std::chrono::time_point<ClockT, DurationT>& atime) noexcept;
226 template <typename ClockT, typename DurationT, typename PredicateT>
227 bool wait_until(std::unique_lock<std::mutex>& lock, const std::chrono::time_point<ClockT, DurationT>& atime,
228 PredicateT p) noexcept;
239 template <typename RepT, typename PeriodT>
240 std::cv_status wait_for(std::unique_lock<std::mutex>& lock,
241 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept;
254 template <typename RepT, typename PeriodT, typename PredicateT>
255 bool wait_for(std::unique_lock<std::mutex>& lock, const std::chrono::duration<RepT, PeriodT>& rtime,
256 PredicateT p) noexcept;
263 [[nodiscard]] native_handle_type native_handle() noexcept;
266 template <typename ToDurT, typename RepT, typename PeriodT>
267 static constexpr ToDurT ceil(const std::chrono::duration<RepT, PeriodT>& d) noexcept;
269 template <typename TpT, typename UpT>
270 static constexpr TpT ceil_impl(const TpT& t, const UpT& u) noexcept;
272 template <typename DurationT>
273 std::cv_status wait_until_impl(std::unique_lock<std::mutex>& lock,
274 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
276 pthread_cond_t cond_{};
310 void notify_one() noexcept;
315 void notify_all() noexcept;
323 template <typename LockT>
324 void wait(LockT& lock) noexcept;
334 template <typename LockT, typename PredicateT>
335 void wait(LockT& lock, PredicateT p) noexcept;
347 template <typename LockT, typename ClockT, typename DurationT>
348 std::cv_status wait_until(LockT& lock, const std::chrono::time_point<ClockT, DurationT>& atime) noexcept;
362 template <typename LockT, typename ClockT, typename DurationT, typename PredicateT>
363 bool wait_until(LockT& lock, const std::chrono::time_point<ClockT, DurationT>& atime, PredicateT p) noexcept;
375 template <typename LockT, typename RepT, typename PeriodT>
376 std::cv_status wait_for(LockT& lock, const std::chrono::duration<RepT, PeriodT>& rtime) noexcept;
390 template <typename LockT, typename RepT, typename PeriodT, typename PredicateT>
391 bool wait_for(LockT& lock, const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p) noexcept;
394 template <typename ToDurT, typename RepT, typename PeriodT>
395 static constexpr ToDurT ceil(const std::chrono::duration<RepT, PeriodT>& d) noexcept;
397 template <typename TpT, typename UpT>
398 static constexpr TpT ceil_impl(const TpT& t, const UpT& u) noexcept;
400 template <typename LockT, typename DurationT>
401 std::cv_status wait_until_impl(LockT& lock,
402 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
404 struct SharedState final {
409 std::shared_ptr<SharedState> shared_state_;
416inline ConditionVariable::ConditionVariable() noexcept {
417 pthread_condattr_t attr;
419 pthread_condattr_init(&attr);
420 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
421 pthread_cond_init(&cond_, &attr);
422 pthread_condattr_destroy(&attr);
425inline ConditionVariable::~ConditionVariable() noexcept { pthread_cond_destroy(&cond_); }
427inline void ConditionVariable::notify_one() noexcept { pthread_cond_signal(&cond_); }
429inline void ConditionVariable::notify_all() noexcept { pthread_cond_broadcast(&cond_); }
431inline void ConditionVariable::wait(std::unique_lock<std::mutex>& lock)
noexcept {
432 pthread_cond_wait(&cond_, lock.mutex()->native_handle());
435template <
typename PredicateT>
436inline void ConditionVariable::wait(std::unique_lock<std::mutex>& lock, PredicateT p)
noexcept {
442template <
typename DurationT>
443inline std::cv_status ConditionVariable::wait_until(
444 std::unique_lock<std::mutex>& lock,
445 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime)
noexcept {
446 return wait_until_impl(lock, atime);
449template <
typename DurationT>
450inline std::cv_status ConditionVariable::wait_until(
451 std::unique_lock<std::mutex>& lock,
452 const std::chrono::time_point<std::chrono::system_clock, DurationT>& atime)
noexcept {
453 return wait_until<std::chrono::system_clock, DurationT>(lock, atime);
456template <
typename ClockT,
typename DurationT>
457inline std::cv_status ConditionVariable::wait_until(std::unique_lock<std::mutex>& lock,
458 const std::chrono::time_point<ClockT, DurationT>& atime)
noexcept {
459 const typename ClockT::time_point c_entry = ClockT::now();
460 const std::chrono::steady_clock::time_point s_entry = std::chrono::steady_clock::now();
461 const auto delta = atime - c_entry;
462 const auto s_atime = s_entry + ceil<std::chrono::steady_clock::duration>(delta);
464 if (wait_until_impl(lock, s_atime) == std::cv_status::no_timeout) {
465 return std::cv_status::no_timeout;
468 if (ClockT::now() < atime) {
469 return std::cv_status::no_timeout;
472 return std::cv_status::timeout;
475template <
typename ClockT,
typename DurationT,
typename PredicateT>
476inline bool ConditionVariable::wait_until(std::unique_lock<std::mutex>& lock,
477 const std::chrono::time_point<ClockT, DurationT>& atime,
478 PredicateT p)
noexcept {
480 if (wait_until(lock, atime) == std::cv_status::timeout) {
488template <
typename RepT,
typename PeriodT>
489inline std::cv_status ConditionVariable::wait_for(std::unique_lock<std::mutex>& lock,
490 const std::chrono::duration<RepT, PeriodT>& rtime)
noexcept {
491 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime));
494template <
typename RepT,
typename PeriodT,
typename PredicateT>
495inline bool ConditionVariable::wait_for(std::unique_lock<std::mutex>& lock,
496 const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p)
noexcept {
497 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime),
501inline ConditionVariable::native_handle_type ConditionVariable::native_handle() noexcept {
return &cond_; }
503template <
typename ToDurT,
typename RepT,
typename PeriodT>
504inline constexpr ToDurT ConditionVariable::ceil(
const std::chrono::duration<RepT, PeriodT>& d)
noexcept {
505 return ceil_impl(std::chrono::duration_cast<ToDurT>(d), d);
508template <
typename TpT,
typename UpT>
509inline constexpr TpT ConditionVariable::ceil_impl(
const TpT& t,
const UpT& u)
noexcept {
510 return (t < u) ? (t + TpT{1}) : t;
513template <
typename DurationT>
514inline std::cv_status ConditionVariable::wait_until_impl(
515 std::unique_lock<std::mutex>& lock,
516 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime)
noexcept {
517 if (std::chrono::steady_clock::now() >= atime) {
518 return std::cv_status::timeout;
521 auto s = std::chrono::time_point_cast<std::chrono::seconds>(atime);
522 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(atime - s);
524 struct timespec ts = {
static_cast<std::time_t
>(s.time_since_epoch().count()),
525 static_cast<long>(ns.count())};
527 int ret = pthread_cond_timedwait(&cond_, lock.mutex()->native_handle(), &ts);
529 return (ret == ETIMEDOUT) ? std::cv_status::timeout : std::cv_status::no_timeout;
532inline ConditionVariableAny::ConditionVariableAny() noexcept : shared_state_(std::make_shared<SharedState>()) {}
534inline ConditionVariableAny::~ConditionVariableAny() noexcept = default;
537 std::shared_ptr<SharedState> state = shared_state_;
538 std::lock_guard<std::mutex> lock(state->mtx);
539 state->cv.notify_one();
542inline void ConditionVariableAny::notify_all() noexcept {
543 std::shared_ptr<SharedState> state = shared_state_;
544 std::lock_guard<std::mutex> lock(state->mtx);
545 state->cv.notify_all();
548template <
typename LockT>
549inline void ConditionVariableAny::wait(LockT& lock)
noexcept {
550 std::shared_ptr<SharedState> state = shared_state_;
551 std::unique_lock<std::mutex> internal_lock(state->mtx);
554 struct UnlockGuard final {
557 ~UnlockGuard() noexcept {
560 }
catch (std::exception&) {
565 state->cv.wait(internal_lock);
568template <
typename LockT,
typename PredicateT>
569inline void ConditionVariableAny::wait(LockT& lock, PredicateT p)
noexcept {
575template <
typename LockT,
typename ClockT,
typename DurationT>
576inline std::cv_status ConditionVariableAny::wait_until(
577 LockT& lock,
const std::chrono::time_point<ClockT, DurationT>& atime)
noexcept {
578 if constexpr (std::is_same_v<ClockT, std::chrono::steady_clock>) {
579 return wait_until_impl(lock, atime);
581 const typename ClockT::time_point c_entry = ClockT::now();
582 const std::chrono::steady_clock::time_point s_entry = std::chrono::steady_clock::now();
583 const auto delta = atime - c_entry;
584 const auto s_atime = s_entry + ceil<std::chrono::steady_clock::duration>(delta);
586 if (wait_until_impl(lock, s_atime) == std::cv_status::no_timeout) {
587 return std::cv_status::no_timeout;
590 if (ClockT::now() < atime) {
591 return std::cv_status::no_timeout;
594 return std::cv_status::timeout;
598template <
typename LockT,
typename ClockT,
typename DurationT,
typename PredicateT>
599inline bool ConditionVariableAny::wait_until(LockT& lock,
const std::chrono::time_point<ClockT, DurationT>& atime,
600 PredicateT p)
noexcept {
602 if (wait_until(lock, atime) == std::cv_status::timeout) {
610template <
typename LockT,
typename RepT,
typename PeriodT>
611inline std::cv_status ConditionVariableAny::wait_for(LockT& lock,
612 const std::chrono::duration<RepT, PeriodT>& rtime)
noexcept {
613 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime));
616template <
typename LockT,
typename RepT,
typename PeriodT,
typename PredicateT>
617inline bool ConditionVariableAny::wait_for(LockT& lock,
const std::chrono::duration<RepT, PeriodT>& rtime,
618 PredicateT p)
noexcept {
619 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime),
623template <
typename ToDurT,
typename RepT,
typename PeriodT>
624inline constexpr ToDurT ConditionVariableAny::ceil(
const std::chrono::duration<RepT, PeriodT>& d)
noexcept {
625 return ceil_impl(std::chrono::duration_cast<ToDurT>(d), d);
628template <
typename TpT,
typename UpT>
629inline constexpr TpT ConditionVariableAny::ceil_impl(
const TpT& t,
const UpT& u)
noexcept {
630 return (t < u) ? (t + TpT{1}) : t;
633template <
typename LockT,
typename DurationT>
634inline std::cv_status ConditionVariableAny::wait_until_impl(
635 LockT& lock,
const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime)
noexcept {
636 if (std::chrono::steady_clock::now() >= atime) {
637 return std::cv_status::timeout;
640 std::shared_ptr<SharedState> state = shared_state_;
641 std::unique_lock<std::mutex> internal_lock(state->mtx);
644 struct UnlockGuard final {
647 ~UnlockGuard() noexcept {
650 }
catch (std::exception&) {
655 auto s = std::chrono::time_point_cast<std::chrono::seconds>(atime);
656 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(atime - s);
658 struct timespec ts = {
static_cast<std::time_t
>(s.time_since_epoch().count()),
659 static_cast<long>(ns.count())};
661 int ret = pthread_cond_timedwait(state->cv.native_handle(), internal_lock.mutex()->native_handle(), &ts);
663 return (ret == ETIMEDOUT) ? std::cv_status::timeout : std::cv_status::no_timeout;
std::condition_variable_any ConditionVariableAny
Definition condition_variable.h:685
ConditionVariableAny condition_variable_any
Definition condition_variable.h:687
ConditionVariable condition_variable
Definition condition_variable.h:686
std::condition_variable ConditionVariable
Definition condition_variable.h:684