zpp
Zephyr C++20 Framework
condition_variable.hpp
Go to the documentation of this file.
1 
7 #ifndef ZPP_INCLUDE_ZPP_CONDITION_VARIABLE_HPP
8 #define ZPP_INCLUDE_ZPP_CONDITION_VARIABLE_HPP
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #include <chrono>
14 
15 #include <zpp/mutex.hpp>
16 #include <zpp/utils.hpp>
17 #include <zpp/result.hpp>
18 #include <zpp/error_code.hpp>
19 
20 namespace zpp {
21 
25 template<typename T_ConditionVariable>
27 {
28 public:
29  using native_type = struct k_condvar;
32 protected:
36  constexpr condition_variable_base() noexcept = default;
37 public:
38 
44  [[nodiscard]] auto notify_one() noexcept
45  {
47 
48  auto rc = k_condvar_signal(native_handle());
49  if (rc == 0) {
50  res.assign_value();
51  } else {
52  res.assign_error(to_error_code(-rc));
53  }
54 
55  return res;
56  }
57 
63  [[nodiscard]] auto notify_all() noexcept
64  {
66 
67  auto rc = k_condvar_broadcast(native_handle());
68  if (rc == 0) {
69  res.assign_value();
70  } else {
71  res.assign_error(to_error_code(-rc));
72  }
73 
74  return res;
75  }
76 
84  template<class T_Mutex>
85  [[nodiscard]] auto wait(T_Mutex& m) noexcept
86  {
88 
89  auto h = m.native_handle();
90  if (h == nullptr) {
92  } else {
93  auto rc = k_condvar_wait(native_handle(), h, K_FOREVER);
94  if (rc == 0) {
95  res.assign_value();
96  } else {
97  res.assign_error(to_error_code(-rc));
98  }
99  }
100 
101  return res;
102  }
103 
112  template <class T_Mutex, class T_Rep, class T_Period>
113  [[nodiscard]] auto
114  try_wait_for(T_Mutex& m, const std::chrono::duration<T_Rep, T_Period>& timeout) noexcept
115  {
116  using namespace std::chrono;
117 
119 
120  auto h = m.native_handle();
121  if (h == nullptr) {
123  } else {
124  auto rc = k_condvar_wait(native_handle(), h, to_timeout(timeout));
125  if (rc == 0) {
126  res.assign_value();
127  } else {
128  res.assign_error(to_error_code(-rc));
129  }
130  }
131 
132  return res;
133  }
134 
135 
144  template<class T_Mutex, class T_Predecate>
145  [[nodiscard]] auto wait(T_Mutex& m, T_Predecate pred) noexcept
146  {
148 
149  auto h = m.native_handle();
150  if (h == nullptr) {
152  } else {
153  while (pred() == false) {
154  auto rc = k_condvar_wait(native_handle(), h, K_FOREVER);
155  if (rc != 0) {
156  res.assign_error(to_error_code(-rc));
157  return res;
158  }
159  }
160 
161  res.assign_value();
162  }
163 
164  return res;
165  }
166 
176  template <class T_Mutex, class T_Rep, class T_Period, class T_Predecate>
177  [[nodiscard]] auto
178  try_wait_for(T_Mutex& m, const std::chrono::duration<T_Rep, T_Period>& timeout, T_Predecate pred) noexcept
179  {
180  using namespace std::chrono;
181 
183 
184  auto h = m.native_handle();
185  if (h == nullptr) {
187  } else {
188  while(pred() == false) {
189  auto rc = k_condvar_wait(native_handle(), h, to_timeout(timeout));
190  if (rc != 0) {
191  res.assign_error(to_error_code(-rc));
192  return res;
193  }
194 
195  // TODO update timeout
196  }
197 
198  res.assign_value();
199  }
200 
201  return res;
202  }
203 
209  [[nodiscard]] auto native_handle() noexcept -> native_pointer
210  {
211  return static_cast<T_ConditionVariable*>(this)->native_handle();
212  }
213 
219  auto native_handle() const noexcept -> native_const_pointer
220  {
221  return static_cast<const T_ConditionVariable*>(this)->native_handle();
222  }
223 public:
228 };
229 
234  : public condition_variable_base<condition_variable> {
235 public:
240  {
241  k_condvar_init(&m_condvar);
242  }
243 
249  [[nodiscard]] constexpr auto native_handle() noexcept -> native_pointer
250  {
251  return &m_condvar;
252  }
258  [[nodiscard]] constexpr auto native_handle() const noexcept -> native_const_pointer
259  {
260  return &m_condvar;
261  }
262 private:
263  native_type m_condvar{};
264 public:
269 };
270 
279  : public condition_variable_base<condition_variable_ref> {
280 public:
289  explicit constexpr condition_variable_ref(native_pointer cv) noexcept
290  : m_condvar_ptr(cv)
291  {
292  __ASSERT_NO_MSG(m_condvar_ptr != nullptr);
293  }
294 
303  template<class T_ContitionVariable>
304  explicit constexpr condition_variable_ref(const T_ContitionVariable& cv) noexcept
305  : m_condvar_ptr(cv.native_handle())
306  {
307  __ASSERT_NO_MSG(m_condvar_ptr != nullptr);
308  }
309 
319  {
320  m_condvar_ptr = cv;
321  __ASSERT_NO_MSG(m_condvar_ptr != nullptr);
322  return *this;
323  }
324 
333  template<class T_ContitionVariable>
334  condition_variable_ref& operator=(const T_ContitionVariable& cv) noexcept
335  {
336  m_condvar_ptr = cv.native_handle();
337  __ASSERT_NO_MSG(m_condvar_ptr != nullptr);
338  return *this;
339  }
340 
346  [[nodiscard]] constexpr auto native_handle() noexcept -> native_pointer
347  {
348  __ASSERT_NO_MSG(m_condvar_ptr != nullptr);
349 
350  return m_condvar_ptr;
351  }
352 
358  [[nodiscard]] constexpr auto native_handle() const noexcept -> native_const_pointer
359  {
360  __ASSERT_NO_MSG(m_condvar_ptr != nullptr);
361 
362  return m_condvar_ptr;
363  }
364 private:
365  native_pointer m_condvar_ptr{ nullptr };
366 };
367 
368 } // namespace zpp
369 
370 #endif // ZPP_INCLUDE_ZPP_CONDITION_VARIABLE_HPP
A condition variable CRTP base class.
condition_variable_base & operator=(condition_variable_base &&)=delete
auto notify_one() noexcept
Notify one waiter.
auto native_handle() noexcept -> native_pointer
get the native zephyr k_condvar pointer.
constexpr condition_variable_base() noexcept=default
Protected default constructor so only derived classes can be created.
auto try_wait_for(T_Mutex &m, const std::chrono::duration< T_Rep, T_Period > &timeout) noexcept
Try waiting with a timeout to see if the variable is signaled.
condition_variable_base(const condition_variable_base &)=delete
auto wait(T_Mutex &m) noexcept
wait for ever until the variable is signaled.
condition_variable_base & operator=(const condition_variable_base &)=delete
auto try_wait_for(T_Mutex &m, const std::chrono::duration< T_Rep, T_Period > &timeout, T_Predecate pred) noexcept
Try waiting with a timeout to see if the variable is signaled.
auto notify_all() noexcept
Notify all waiters.
auto wait(T_Mutex &m, T_Predecate pred) noexcept
wait for ever until the variable is signaled.
auto native_handle() const noexcept -> native_const_pointer
get the native zephyr k_condvar pointer.
native_type const * native_const_pointer
condition_variable_base(condition_variable_base &&)=delete
A class using a reference to another native condition variable or zpp::condition_variable.
condition_variable_ref & operator=(const T_ContitionVariable &cv) noexcept
copy a condition variable using another condition variable
constexpr auto native_handle() const noexcept -> native_const_pointer
get the native zephyr condition variable handle.
constexpr auto native_handle() noexcept -> native_pointer
get the native zephyr condition variable handle.
constexpr condition_variable_ref(const T_ContitionVariable &cv) noexcept
Construct a condition variable using another condition variable.
condition_variable_ref & operator=(native_pointer cv) noexcept
copy a condition variable using another condition variable
constexpr condition_variable_ref(native_pointer cv) noexcept
Construct a condition variable using a native k_condvar*.
A condition variable class.
condition_variable(const condition_variable &)=delete
condition_variable & operator=(condition_variable &&)=delete
condition_variable() noexcept
Default constructor.
condition_variable(condition_variable &&)=delete
condition_variable & operator=(const condition_variable &)=delete
constexpr auto native_handle() const noexcept -> native_const_pointer
get the native zephyr condition variable handle.
constexpr auto native_handle() noexcept -> native_pointer
get the native zephyr condition variable handle.
result class
Definition: result.hpp:89
void assign_value(const T_Ok &v) noexcept
Definition: result.hpp:197
void assign_error(const T_Error &e) noexcept
Definition: result.hpp:219
constexpr error_code to_error_code(int v) noexcept
Definition: error_code.hpp:102
constexpr k_timeout_t to_timeout(const std::chrono::duration< T_Rep, T_Period > &d) noexcept
convert a duration to tick
Definition: clock.hpp:88
@ k_inval
Invalid argument.