87 #include <condition_variable>
89 #if !defined(VLINK_ENABLE_BASE_CONDITION) && defined(__unix__) && !defined(__CYGWIN__)
90 #define VLINK_ENABLE_BASE_CONDITION
93 #ifdef VLINK_ENABLE_BASE_CONDITION
120 using native_handle_type = pthread_cond_t*;
139 void notify_one() noexcept;
144 void notify_all() noexcept;
151 void wait(std::unique_lock<std::mutex>& lock) noexcept;
161 template <typename PredicateT>
162 void wait(std::unique_lock<std::mutex>& lock, PredicateT p);
172 template <typename DurationT>
173 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
174 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
184 template <typename DurationT>
185 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
186 const std::chrono::time_point<std::chrono::system_clock, DurationT>& atime) noexcept;
197 template <typename ClockT, typename DurationT>
198 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
199 const std::chrono::time_point<ClockT, DurationT>& atime) noexcept;
213 template <typename ClockT, typename DurationT, typename PredicateT>
214 bool wait_until(std::unique_lock<std::mutex>& lock, const std::chrono::time_point<ClockT, DurationT>& atime,
226 template <typename RepT, typename PeriodT>
227 std::cv_status wait_for(std::unique_lock<std::mutex>& lock,
228 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept;
242 template <typename RepT, typename PeriodT, typename PredicateT>
243 bool wait_for(std::unique_lock<std::mutex>& lock, const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p);
250 [[nodiscard]] native_handle_type native_handle() noexcept;
253 template <typename ToDurT, typename RepT, typename PeriodT>
254 static constexpr ToDurT ceil(const std::chrono::duration<RepT, PeriodT>& d) noexcept;
256 template <typename TpT, typename UpT>
257 static constexpr TpT ceil_impl(const TpT& t, const UpT& u) noexcept;
259 std::cv_status wait_until_steady(std::unique_lock<std::mutex>& lock,
260 const std::chrono::steady_clock::time_point& atime) noexcept;
262 pthread_cond_t cond_{};
297 void notify_one() noexcept;
302 void notify_all() noexcept;
310 template <typename LockT>
311 void wait(LockT& lock) noexcept;
322 template <typename LockT, typename PredicateT>
323 void wait(LockT& lock, PredicateT p);
335 template <typename LockT, typename ClockT, typename DurationT>
336 std::cv_status wait_until(LockT& lock, const std::chrono::time_point<ClockT, DurationT>& atime) noexcept;
351 template <typename LockT, typename ClockT, typename DurationT, typename PredicateT>
352 bool wait_until(LockT& lock, const std::chrono::time_point<ClockT, DurationT>& atime, PredicateT p);
364 template <typename LockT, typename RepT, typename PeriodT>
365 std::cv_status wait_for(LockT& lock, const std::chrono::duration<RepT, PeriodT>& rtime) noexcept;
380 template <typename LockT, typename RepT, typename PeriodT, typename PredicateT>
381 bool wait_for(LockT& lock, const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p);
384 template <typename ToDurT, typename RepT, typename PeriodT>
385 static constexpr ToDurT ceil(const std::chrono::duration<RepT, PeriodT>& d) noexcept;
387 template <typename TpT, typename UpT>
388 static constexpr TpT ceil_impl(const TpT& t, const UpT& u) noexcept;
390 template <typename LockT, typename DurationT>
391 std::cv_status wait_until_impl(LockT& lock,
392 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
394 struct SharedState final {
399 std::shared_ptr<SharedState> shared_state_;
406 template <
typename PredicateT>
407 inline void ConditionVariable::wait(std::unique_lock<std::mutex>& lock, PredicateT p) {
413 template <
typename DurationT>
414 inline std::cv_status ConditionVariable::wait_until(
415 std::unique_lock<std::mutex>& lock,
416 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept {
417 return wait_until_steady(lock, std::chrono::time_point_cast<std::chrono::steady_clock::duration>(atime));
420 template <
typename DurationT>
421 inline std::cv_status ConditionVariable::wait_until(
422 std::unique_lock<std::mutex>& lock,
423 const std::chrono::time_point<std::chrono::system_clock, DurationT>& atime) noexcept {
424 return wait_until<std::chrono::system_clock, DurationT>(lock, atime);
427 template <
typename ClockT,
typename DurationT>
428 inline std::cv_status ConditionVariable::wait_until(std::unique_lock<std::mutex>& lock,
429 const std::chrono::time_point<ClockT, DurationT>& atime) noexcept {
430 const typename ClockT::time_point c_entry = ClockT::now();
431 const std::chrono::steady_clock::time_point s_entry = std::chrono::steady_clock::now();
432 const auto delta = atime - c_entry;
433 const auto s_atime = s_entry + ceil<std::chrono::steady_clock::duration>(delta);
435 if (wait_until_steady(lock, s_atime) == std::cv_status::no_timeout) {
436 return std::cv_status::no_timeout;
439 if (ClockT::now() < atime) {
440 return std::cv_status::no_timeout;
443 return std::cv_status::timeout;
446 template <
typename ClockT,
typename DurationT,
typename PredicateT>
447 inline bool ConditionVariable::wait_until(std::unique_lock<std::mutex>& lock,
448 const std::chrono::time_point<ClockT, DurationT>& atime, PredicateT p) {
450 if (wait_until(lock, atime) == std::cv_status::timeout) {
458 template <
typename RepT,
typename PeriodT>
459 inline std::cv_status ConditionVariable::wait_for(std::unique_lock<std::mutex>& lock,
460 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept {
461 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime));
464 template <
typename RepT,
typename PeriodT,
typename PredicateT>
465 inline bool ConditionVariable::wait_for(std::unique_lock<std::mutex>& lock,
466 const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p) {
467 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime),
471 template <
typename ToDurT,
typename RepT,
typename PeriodT>
472 inline constexpr ToDurT ConditionVariable::ceil(
const std::chrono::duration<RepT, PeriodT>& d) noexcept {
473 return ceil_impl(std::chrono::duration_cast<ToDurT>(d), d);
476 template <
typename TpT,
typename UpT>
477 inline constexpr TpT ConditionVariable::ceil_impl(
const TpT& t,
const UpT& u) noexcept {
478 return (t < u) ? (t + TpT{1}) : t;
481 template <
typename LockT>
482 inline void ConditionVariableAny::wait(LockT& lock) noexcept {
483 std::shared_ptr<SharedState> state = shared_state_;
484 std::unique_lock internal_lock(state->mtx);
487 struct UnlockGuard final {
490 ~UnlockGuard() noexcept {
493 }
catch (std::exception&) {
498 state->cv.wait(internal_lock);
499 internal_lock.unlock();
502 template <
typename LockT,
typename PredicateT>
503 inline void ConditionVariableAny::wait(LockT& lock, PredicateT p) {
509 template <
typename LockT,
typename ClockT,
typename DurationT>
510 inline std::cv_status ConditionVariableAny::wait_until(
511 LockT& lock,
const std::chrono::time_point<ClockT, DurationT>& atime) noexcept {
512 if constexpr (std::is_same_v<ClockT, std::chrono::steady_clock>) {
513 return wait_until_impl(lock, atime);
515 const typename ClockT::time_point c_entry = ClockT::now();
516 const std::chrono::steady_clock::time_point s_entry = std::chrono::steady_clock::now();
517 const auto delta = atime - c_entry;
518 const auto s_atime = s_entry + ceil<std::chrono::steady_clock::duration>(delta);
520 if (wait_until_impl(lock, s_atime) == std::cv_status::no_timeout) {
521 return std::cv_status::no_timeout;
524 if (ClockT::now() < atime) {
525 return std::cv_status::no_timeout;
528 return std::cv_status::timeout;
532 template <
typename LockT,
typename ClockT,
typename DurationT,
typename PredicateT>
533 inline bool ConditionVariableAny::wait_until(LockT& lock,
const std::chrono::time_point<ClockT, DurationT>& atime,
536 if (wait_until(lock, atime) == std::cv_status::timeout) {
544 template <
typename LockT,
typename RepT,
typename PeriodT>
545 inline std::cv_status ConditionVariableAny::wait_for(LockT& lock,
546 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept {
547 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime));
550 template <
typename LockT,
typename RepT,
typename PeriodT,
typename PredicateT>
551 inline bool ConditionVariableAny::wait_for(LockT& lock,
const std::chrono::duration<RepT, PeriodT>& rtime,
553 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime),
557 template <
typename ToDurT,
typename RepT,
typename PeriodT>
558 inline constexpr ToDurT ConditionVariableAny::ceil(
const std::chrono::duration<RepT, PeriodT>& d) noexcept {
559 return ceil_impl(std::chrono::duration_cast<ToDurT>(d), d);
562 template <
typename TpT,
typename UpT>
563 inline constexpr TpT ConditionVariableAny::ceil_impl(
const TpT& t,
const UpT& u) noexcept {
564 return (t < u) ? (t + TpT{1}) : t;
567 template <
typename LockT,
typename DurationT>
568 inline std::cv_status ConditionVariableAny::wait_until_impl(
569 LockT& lock,
const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept {
570 if (std::chrono::steady_clock::now() >= atime) {
571 return std::cv_status::timeout;
574 std::shared_ptr<SharedState> state = shared_state_;
575 std::unique_lock internal_lock(state->mtx);
578 struct UnlockGuard final {
581 ~UnlockGuard() noexcept {
584 }
catch (std::exception&) {
589 const auto status = state->cv.wait_until(internal_lock, atime);
590 internal_lock.unlock();
Cross-platform macros for visibility, branch hints, copy prevention, singletons and string helpers.
#define VLINK_EXPORT
Definition: macros.h:81
std::condition_variable_any ConditionVariableAny
Definition: condition_variable.h:614
std::condition_variable ConditionVariable
Definition: condition_variable.h:613
ConditionVariableAny condition_variable_any
Definition: condition_variable.h:616
ConditionVariable condition_variable
Definition: condition_variable.h:615