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;
160 template <typename PredicateT>
161 void wait(std::unique_lock<std::mutex>& lock, PredicateT p) noexcept;
171 template <typename DurationT>
172 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
173 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
183 template <typename DurationT>
184 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
185 const std::chrono::time_point<std::chrono::system_clock, DurationT>& atime) noexcept;
196 template <typename ClockT, typename DurationT>
197 std::cv_status wait_until(std::unique_lock<std::mutex>& lock,
198 const std::chrono::time_point<ClockT, DurationT>& atime) noexcept;
211 template <typename ClockT, typename DurationT, typename PredicateT>
212 bool wait_until(std::unique_lock<std::mutex>& lock, const std::chrono::time_point<ClockT, DurationT>& atime,
213 PredicateT p) noexcept;
224 template <typename RepT, typename PeriodT>
225 std::cv_status wait_for(std::unique_lock<std::mutex>& lock,
226 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept;
239 template <typename RepT, typename PeriodT, typename PredicateT>
240 bool wait_for(std::unique_lock<std::mutex>& lock, const std::chrono::duration<RepT, PeriodT>& rtime,
241 PredicateT p) noexcept;
248 [[nodiscard]] native_handle_type native_handle() noexcept;
251 template <typename ToDurT, typename RepT, typename PeriodT>
252 static constexpr ToDurT ceil(const std::chrono::duration<RepT, PeriodT>& d) noexcept;
254 template <typename TpT, typename UpT>
255 static constexpr TpT ceil_impl(const TpT& t, const UpT& u) noexcept;
257 std::cv_status wait_until_steady(std::unique_lock<std::mutex>& lock,
258 const std::chrono::steady_clock::time_point& atime) noexcept;
260 pthread_cond_t cond_{};
295 void notify_one() noexcept;
300 void notify_all() noexcept;
308 template <typename LockT>
309 void wait(LockT& lock) noexcept;
319 template <typename LockT, typename PredicateT>
320 void wait(LockT& lock, PredicateT p) noexcept;
332 template <typename LockT, typename ClockT, typename DurationT>
333 std::cv_status wait_until(LockT& lock, const std::chrono::time_point<ClockT, DurationT>& atime) noexcept;
347 template <typename LockT, typename ClockT, typename DurationT, typename PredicateT>
348 bool wait_until(LockT& lock, const std::chrono::time_point<ClockT, DurationT>& atime, PredicateT p) noexcept;
360 template <typename LockT, typename RepT, typename PeriodT>
361 std::cv_status wait_for(LockT& lock, const std::chrono::duration<RepT, PeriodT>& rtime) noexcept;
375 template <typename LockT, typename RepT, typename PeriodT, typename PredicateT>
376 bool wait_for(LockT& lock, const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p) noexcept;
379 template <typename ToDurT, typename RepT, typename PeriodT>
380 static constexpr ToDurT ceil(const std::chrono::duration<RepT, PeriodT>& d) noexcept;
382 template <typename TpT, typename UpT>
383 static constexpr TpT ceil_impl(const TpT& t, const UpT& u) noexcept;
385 template <typename LockT, typename DurationT>
386 std::cv_status wait_until_impl(LockT& lock,
387 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept;
389 struct SharedState final {
394 std::shared_ptr<SharedState> shared_state_;
401 template <
typename PredicateT>
402 inline void ConditionVariable::wait(std::unique_lock<std::mutex>& lock, PredicateT p) noexcept {
408 template <
typename DurationT>
409 inline std::cv_status ConditionVariable::wait_until(
410 std::unique_lock<std::mutex>& lock,
411 const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept {
412 return wait_until_steady(lock, std::chrono::time_point_cast<std::chrono::steady_clock::duration>(atime));
415 template <
typename DurationT>
416 inline std::cv_status ConditionVariable::wait_until(
417 std::unique_lock<std::mutex>& lock,
418 const std::chrono::time_point<std::chrono::system_clock, DurationT>& atime) noexcept {
419 return wait_until<std::chrono::system_clock, DurationT>(lock, atime);
422 template <
typename ClockT,
typename DurationT>
423 inline std::cv_status ConditionVariable::wait_until(std::unique_lock<std::mutex>& lock,
424 const std::chrono::time_point<ClockT, DurationT>& atime) noexcept {
425 const typename ClockT::time_point c_entry = ClockT::now();
426 const std::chrono::steady_clock::time_point s_entry = std::chrono::steady_clock::now();
427 const auto delta = atime - c_entry;
428 const auto s_atime = s_entry + ceil<std::chrono::steady_clock::duration>(delta);
430 if (wait_until_steady(lock, s_atime) == std::cv_status::no_timeout) {
431 return std::cv_status::no_timeout;
434 if (ClockT::now() < atime) {
435 return std::cv_status::no_timeout;
438 return std::cv_status::timeout;
441 template <
typename ClockT,
typename DurationT,
typename PredicateT>
442 inline bool ConditionVariable::wait_until(std::unique_lock<std::mutex>& lock,
443 const std::chrono::time_point<ClockT, DurationT>& atime,
444 PredicateT p) noexcept {
446 if (wait_until(lock, atime) == std::cv_status::timeout) {
454 template <
typename RepT,
typename PeriodT>
455 inline std::cv_status ConditionVariable::wait_for(std::unique_lock<std::mutex>& lock,
456 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept {
457 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime));
460 template <
typename RepT,
typename PeriodT,
typename PredicateT>
461 inline bool ConditionVariable::wait_for(std::unique_lock<std::mutex>& lock,
462 const std::chrono::duration<RepT, PeriodT>& rtime, PredicateT p) noexcept {
463 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime),
467 template <
typename ToDurT,
typename RepT,
typename PeriodT>
468 inline constexpr ToDurT ConditionVariable::ceil(
const std::chrono::duration<RepT, PeriodT>& d) noexcept {
469 return ceil_impl(std::chrono::duration_cast<ToDurT>(d), d);
472 template <
typename TpT,
typename UpT>
473 inline constexpr TpT ConditionVariable::ceil_impl(
const TpT& t,
const UpT& u) noexcept {
474 return (t < u) ? (t + TpT{1}) : t;
477 template <
typename LockT>
478 inline void ConditionVariableAny::wait(LockT& lock) noexcept {
479 std::shared_ptr<SharedState> state = shared_state_;
480 std::unique_lock internal_lock(state->mtx);
483 struct UnlockGuard final {
486 ~UnlockGuard() noexcept {
489 }
catch (std::exception&) {
494 state->cv.wait(internal_lock);
497 template <
typename LockT,
typename PredicateT>
498 inline void ConditionVariableAny::wait(LockT& lock, PredicateT p) noexcept {
504 template <
typename LockT,
typename ClockT,
typename DurationT>
505 inline std::cv_status ConditionVariableAny::wait_until(
506 LockT& lock,
const std::chrono::time_point<ClockT, DurationT>& atime) noexcept {
507 if constexpr (std::is_same_v<ClockT, std::chrono::steady_clock>) {
508 return wait_until_impl(lock, atime);
510 const typename ClockT::time_point c_entry = ClockT::now();
511 const std::chrono::steady_clock::time_point s_entry = std::chrono::steady_clock::now();
512 const auto delta = atime - c_entry;
513 const auto s_atime = s_entry + ceil<std::chrono::steady_clock::duration>(delta);
515 if (wait_until_impl(lock, s_atime) == std::cv_status::no_timeout) {
516 return std::cv_status::no_timeout;
519 if (ClockT::now() < atime) {
520 return std::cv_status::no_timeout;
523 return std::cv_status::timeout;
527 template <
typename LockT,
typename ClockT,
typename DurationT,
typename PredicateT>
528 inline bool ConditionVariableAny::wait_until(LockT& lock,
const std::chrono::time_point<ClockT, DurationT>& atime,
529 PredicateT p) noexcept {
531 if (wait_until(lock, atime) == std::cv_status::timeout) {
539 template <
typename LockT,
typename RepT,
typename PeriodT>
540 inline std::cv_status ConditionVariableAny::wait_for(LockT& lock,
541 const std::chrono::duration<RepT, PeriodT>& rtime) noexcept {
542 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime));
545 template <
typename LockT,
typename RepT,
typename PeriodT,
typename PredicateT>
546 inline bool ConditionVariableAny::wait_for(LockT& lock,
const std::chrono::duration<RepT, PeriodT>& rtime,
547 PredicateT p) noexcept {
548 return wait_until(lock, std::chrono::steady_clock::now() + ceil<std::chrono::steady_clock::duration>(rtime),
552 template <
typename ToDurT,
typename RepT,
typename PeriodT>
553 inline constexpr ToDurT ConditionVariableAny::ceil(
const std::chrono::duration<RepT, PeriodT>& d) noexcept {
554 return ceil_impl(std::chrono::duration_cast<ToDurT>(d), d);
557 template <
typename TpT,
typename UpT>
558 inline constexpr TpT ConditionVariableAny::ceil_impl(
const TpT& t,
const UpT& u) noexcept {
559 return (t < u) ? (t + TpT{1}) : t;
562 template <
typename LockT,
typename DurationT>
563 inline std::cv_status ConditionVariableAny::wait_until_impl(
564 LockT& lock,
const std::chrono::time_point<std::chrono::steady_clock, DurationT>& atime) noexcept {
565 if (std::chrono::steady_clock::now() >= atime) {
566 return std::cv_status::timeout;
569 std::shared_ptr<SharedState> state = shared_state_;
570 std::unique_lock internal_lock(state->mtx);
573 struct UnlockGuard final {
576 ~UnlockGuard() noexcept {
579 }
catch (std::exception&) {
584 return state->cv.wait_until(internal_lock, atime);
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:606
std::condition_variable ConditionVariable
Definition: condition_variable.h:605
ConditionVariableAny condition_variable_any
Definition: condition_variable.h:608
ConditionVariable condition_variable
Definition: condition_variable.h:607