YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
condition_variable.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <yaclib/log.hpp>
6
7#include <condition_variable>
8#include <tuple>
9#include <yaclib_std/chrono>
10#include <yaclib_std/mutex>
11
12namespace yaclib::detail {
13
14constexpr std::cv_status CVStatusFrom(WaitStatus);
15constexpr std::cv_status CVStatusFrom(std::cv_status);
16
17// TODO(myannyax) unite with ConditionVariableAny
18
19template <typename Impl>
20class ConditionVariable : private Impl {
21 public:
22 using Impl::Impl;
23#ifndef _MSC_VER
24 using Impl::native_handle;
25#endif
26
28 YACLIB_INJECT_FAULT(Impl::notify_one());
29 }
31 YACLIB_INJECT_FAULT(Impl::notify_all());
32 }
33
34 void wait(std::unique_lock<yaclib_std::mutex>& lock) {
35 auto [mutex, impl_lock] = From(lock);
36 YACLIB_INJECT_FAULT(Impl::wait(impl_lock));
37 lock = From(mutex, impl_lock);
38 }
39
40 template <typename Predicate>
41 void wait(std::unique_lock<yaclib_std::mutex>& lock, Predicate&& stop_waiting) {
42 auto [mutex, impl_lock] = From(lock);
43 YACLIB_INJECT_FAULT(Impl::wait(impl_lock, std::forward<Predicate>(stop_waiting)));
44 lock = From(mutex, impl_lock);
45 }
46
47 template <typename Rep, typename Period>
48 std::cv_status wait_for(std::unique_lock<yaclib_std::mutex>& lock,
49 const std::chrono::duration<Rep, Period>& rel_time) {
50 auto [mutex, impl_lock] = From(lock);
51 YACLIB_INJECT_FAULT(auto r = Impl::wait_for(impl_lock, rel_time));
52 lock = From(mutex, impl_lock);
53 return CVStatusFrom(r);
54 }
55 template <typename Rep, typename Period, typename Predicate>
56 bool wait_for(std::unique_lock<yaclib_std::mutex>& lock, const std::chrono::duration<Rep, Period>& rel_time,
58 auto [mutex, impl_lock] = From(lock);
59 YACLIB_INJECT_FAULT(auto r = Impl::wait_for(impl_lock, rel_time, std::forward<Predicate>(stop_waiting)));
60 lock = From(mutex, impl_lock);
61 return r;
62 }
63
64 template <typename Clock, typename Duration>
65 std::cv_status wait_until(std::unique_lock<yaclib_std::mutex>& lock,
66 const std::chrono::time_point<Clock, Duration>& timeout_time) {
67 auto [mutex, impl_lock] = From(lock);
68 YACLIB_INJECT_FAULT(auto r = Impl::wait_until(impl_lock, timeout_time));
69 lock = From(mutex, impl_lock);
70 return CVStatusFrom(r);
71 }
72 template <typename Clock, typename Duration, typename Predicate>
73 bool wait_until(std::unique_lock<yaclib_std::mutex>& lock,
74 const std::chrono::time_point<Clock, Duration>& timeout_time, Predicate&& stop_waiting) {
75 auto [mutex, impl_lock] = From(lock);
76 YACLIB_INJECT_FAULT(auto r = Impl::wait_until(impl_lock, timeout_time, std::forward<Predicate>(stop_waiting)));
77 lock = From(mutex, impl_lock);
78 return r;
79 }
80
81 private:
82 static auto From(std::unique_lock<yaclib_std::mutex>& lock) {
83 YACLIB_DEBUG(!lock.owns_lock(), "Trying to call wait on not owned lock");
84 auto* mutex = lock.release();
85 // type is specified since some old compilers like clang 8 aren't able to calculate it
86 return std::tuple<yaclib_std::mutex*, std::unique_lock<yaclib_std::mutex::impl_t>>{
87 mutex, std::unique_lock{mutex->GetImpl(), std::adopt_lock}};
88 }
89 static auto From(yaclib_std::mutex* mutex, std::unique_lock<yaclib_std::mutex::impl_t>& lock_impl) {
90 YACLIB_DEBUG(!lock_impl.owns_lock(), "After call wait on not owned lock");
91 std::ignore = lock_impl.release();
92 return std::unique_lock{*mutex, std::adopt_lock};
93 }
94};
95
96} // namespace yaclib::detail
bool wait_for(std::unique_lock< yaclib_std::mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time, Predicate &&stop_waiting)
bool wait_until(std::unique_lock< yaclib_std::mutex > &lock, const std::chrono::time_point< Clock, Duration > &timeout_time, Predicate &&stop_waiting)
std::cv_status wait_until(std::unique_lock< yaclib_std::mutex > &lock, const std::chrono::time_point< Clock, Duration > &timeout_time)
void wait(std::unique_lock< yaclib_std::mutex > &lock, Predicate &&stop_waiting)
std::cv_status wait_for(std::unique_lock< yaclib_std::mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time)
void wait(std::unique_lock< yaclib_std::mutex > &lock)
#define YACLIB_INJECT_FAULT(statement)
Definition inject.hpp:20
#define YACLIB_DEBUG(cond, message)
Definition log.hpp:84
constexpr std::cv_status CVStatusFrom(WaitStatus)
std::mutex mutex
Definition mutex.hpp:28
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25