roo_threads
API Documentation for roo_threads
Loading...
Searching...
No Matches
condition_variable.h
Go to the documentation of this file.
1#pragma once
2
4#include "roo_time.h"
5
6#ifdef ROO_THREADS_USE_CPPSTD
7
8#include <chrono>
9#include <condition_variable>
10
12
13namespace roo_threads {
14/// @brief Backend namespace using C++ standard library synchronization primitives.
15namespace cppstd {
16
17/// @ingroup roo_threads_api_condition_variable
18/// @copydoc roo_threads::doc::cv_status
19enum class cv_status { no_timeout, timeout };
20
21/// @ingroup roo_threads_api_condition_variable
22/// @brief C++ standard library backend implementation of
23/// `roo::condition_variable`.
24/// @copydoc roo_threads::doc::condition_variable
25class condition_variable {
26 public:
27 /// @copydoc roo_threads::doc::condition_variable::condition_variable
28 condition_variable() noexcept : cond_() {}
29
30 condition_variable(const condition_variable&) = delete;
31 condition_variable& operator=(const condition_variable&) = delete;
32
33 /// @copydoc roo_threads::doc::condition_variable::wait
34 void wait(unique_lock<mutex>& lock) noexcept { cond_.wait(lock.lock_); }
35
36 /// @copydoc roo_threads::doc::condition_variable::wait
37 template <class Predicate>
38 void wait(unique_lock<mutex>& lock, Predicate pred) {
39 while (!pred()) wait(lock);
40 }
41
42 /// @copydoc roo_threads::doc::condition_variable::notify_one
43 void notify_one() noexcept { cond_.notify_one(); }
44
45 /// @copydoc roo_threads::doc::condition_variable::notify_all
46 void notify_all() noexcept { cond_.notify_all(); }
47
48 /// @copydoc roo_threads::doc::condition_variable::wait_until
49 cv_status wait_until(unique_lock<mutex>& lock, const roo_time::Uptime& when) {
50 return wait_for(lock, when - roo_time::Uptime::Now());
51 }
52
53 /// @copydoc roo_threads::doc::condition_variable::wait_until
54 template <typename Predicate>
55 bool wait_until(unique_lock<mutex>& lock, const roo_time::Uptime& when,
56 Predicate p) {
57 while (!p())
58 if (wait_until(lock, when) == cv_status::timeout) return p();
59 return true;
60 }
61
62 /// @copydoc roo_threads::doc::condition_variable::wait_for
63 /// @note Wait duration is clamped to a safe upper bound to avoid overflow.
64 cv_status wait_for(unique_lock<mutex>& lock,
65 const roo_time::Duration& duration) {
66 static constexpr int64_t kMaxSafeWaitMicros = 10LL * 24 * 3600 * 1000000;
67 // Protecting against overflow, e.g. wait_for(roo_time::Duration::Max()):
68 // never wait for longer than 10 days; spuriously wake up if needed.
69 // Using safely low max duration of 10 days, as ESP32 seems to overflow at
70 // about 24 days.
71 uint64_t micros = duration.inMicros() >= kMaxSafeWaitMicros
72 ? kMaxSafeWaitMicros
73 : duration.inMicros();
74 return cond_.wait_for(lock.lock_, std::chrono::microseconds(micros)) ==
75 std::cv_status::no_timeout
76 ? cv_status::no_timeout
77 : cv_status::timeout;
78 }
79
80 /// @copydoc roo_threads::doc::condition_variable::wait_for
81 /// @note Wait duration is clamped to a safe upper bound to avoid overflow.
82 template <typename Predicate>
83 bool wait_for(unique_lock<mutex>& lock, const roo_time::Duration& duration,
84 Predicate p) {
85 // Protecting against overflow, e.g. wait_for(roo_time::Duration::Max()):
86 // never wait for longer than 10 days; spuriously wake up if needed.
87 // Using safely low max duration of 10 days, as ESP32 seems to overflow at
88 // about 24 days.
89 static constexpr int64_t kMaxSafeWaitMicros = 10LL * 24 * 3600 * 1000000;
90 int64_t wait_micros = duration.inMicros() < kMaxSafeWaitMicros
91 ? duration.inMicros()
92 : kMaxSafeWaitMicros;
93 return cond_.wait_for(lock.lock_, std::chrono::microseconds(wait_micros),
94 p);
95 }
96
97 private:
98 std::condition_variable cond_;
99};
100
101} // namespace cppstd
102} // namespace roo_threads
103
104#endif // ROO_THREADS_USE_CPPSTD
cv_status
Status returned from timed wait operations.