zpp
Zephyr C++20 Framework
sem.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2019 Erwin Rol <erwin@erwinrol.com>
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6 
7 #ifndef ZPP_INCLUDE_ZPP_SEM_HPP
8 #define ZPP_INCLUDE_ZPP_SEM_HPP
9 
10 #include <zpp/thread.hpp>
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/sys/__assert.h>
14 
15 #include <chrono>
16 #include <limits>
17 
18 namespace zpp {
19 
23 template<typename T_Sem>
24 class sem_base
25 {
26 public:
27  using native_type = struct k_sem;
30 
34  using counter_type = uint32_t;
35 
39  constexpr static counter_type max_count =
40  std::numeric_limits<counter_type>::max();
41 protected:
45  constexpr sem_base() noexcept
46  {
47  }
48 public:
54  [[nodiscard]] bool take() noexcept
55  {
56  if (k_sem_take(native_handle(), K_FOREVER) == 0) {
57  return true;
58  } else {
59  return false;
60  }
61  }
62 
68  [[nodiscard]] bool try_take() noexcept
69  {
70  if (k_sem_take(native_handle(), K_NO_WAIT) == 0) {
71  return true;
72  } else {
73  return false;
74  }
75  }
76 
84  template<class T_Rep, class T_Period>
85  [[nodiscard]] bool
86  try_take_for(const std::chrono::duration<T_Rep, T_Period>&
87  timeout_duration) noexcept
88  {
89  if (k_sem_take(native_handle(), to_timeout(timeout_duration)) == 0) {
90  return true;
91  } else {
92  return false;
93  }
94  }
95 
99  void give() noexcept
100  {
101  k_sem_give(native_handle());
102  }
103 
107  void reset() noexcept
108  {
109  k_sem_reset(native_handle());
110  }
111 
117  counter_type count() noexcept
118  {
119  return k_sem_count_get(native_handle());
120  }
121 
125  void operator++(int) noexcept
126  {
127  give();
128  }
129 
133  void operator--(int) noexcept
134  {
135  while (!take()) {
137  }
138  }
139 
145  void operator+=(int n) noexcept
146  {
147  while (n-- > 0) {
148  give();
149  }
150  }
151 
157  void operator-=(int n) noexcept
158  {
159  while (n-- > 0) {
160  while (!take()) {
162  }
163  }
164  }
165 
171  auto native_handle() noexcept -> native_pointer
172  {
173  return static_cast<T_Sem*>(this)->native_handle();
174  }
175 
181  auto native_handle() const noexcept -> native_const_pointer
182  {
183  return static_cast<const T_Sem*>(this)->native_handle();
184  }
185 public:
186  sem_base(const sem_base&) = delete;
187  sem_base(sem_base&&) = delete;
188  sem_base& operator=(const sem_base&) = delete;
190 };
191 
192 
196 class sem : public sem_base<sem> {
197 public:
204  sem(counter_type initial_count, counter_type count_limit) noexcept
205  {
206  k_sem_init(&m_sem, initial_count, count_limit);
207  }
208 
217  explicit sem(counter_type initial_count) noexcept
218  : sem(initial_count, max_count)
219  {
220  }
221 
227  //
228  sem() noexcept
229  : sem(0, max_count)
230  {
231  }
232 
238  constexpr auto native_handle() noexcept -> native_pointer
239  {
240  return &m_sem;
241  }
242 
248  constexpr auto native_handle() const noexcept -> native_const_pointer
249  {
250  return &m_sem;
251  }
252 private:
253  native_type m_sem;
254 public:
255  sem(const sem&) = delete;
256  sem(sem&&) = delete;
257  sem& operator=(const sem&) = delete;
258  sem& operator=(sem&&) = delete;
259 };
260 
264 class sem_ref : public sem_base<sem_ref> {
265 public:
272  explicit constexpr sem_ref(native_pointer s) noexcept
273  : m_sem_ptr(s)
274  {
275  __ASSERT_NO_MSG(m_sem_ptr != nullptr);
276  }
277 
284  template<class T_Sem>
285  explicit constexpr sem_ref(T_Sem& s) noexcept
286  : m_sem_ptr(s.native_handle())
287  {
288  __ASSERT_NO_MSG(m_sem_ptr != nullptr);
289  }
290 
299  constexpr sem_ref& operator=(native_pointer s) noexcept
300  {
301  m_sem_ptr = s;
302  __ASSERT_NO_MSG(m_sem_ptr != nullptr);
303  return *this;
304  }
305 
314  template<class T_Sem>
315  constexpr sem_ref& operator=(T_Sem& s) noexcept
316  {
317  m_sem_ptr = s.native_handle();
318  __ASSERT_NO_MSG(m_sem_ptr != nullptr);
319  return *this;
320  }
321 
327  constexpr auto native_handle() noexcept -> native_pointer
328  {
329  __ASSERT_NO_MSG(m_sem_ptr != nullptr);
330 
331  return m_sem_ptr;
332  }
333 
339  constexpr auto native_handle() const noexcept -> native_const_pointer
340  {
341  __ASSERT_NO_MSG(m_sem_ptr != nullptr);
342 
343  return m_sem_ptr;
344  }
345 private:
346  native_pointer m_sem_ptr{ nullptr };
347 public:
348  sem_ref() = delete;
349 };
350 
351 } // namespace zpp
352 
353 #endif // ZPP_INCLUDE_ZPP_SEM_HPP
Counting semaphore base class.
Definition: sem.hpp:25
void operator+=(int n) noexcept
Give the semaphore n times.
Definition: sem.hpp:145
auto native_handle() const noexcept -> native_const_pointer
get the native zephyr sem handle.
Definition: sem.hpp:181
void give() noexcept
Give the semaphore.
Definition: sem.hpp:99
native_type * native_pointer
Definition: sem.hpp:28
sem_base & operator=(sem_base &&)=delete
void operator-=(int n) noexcept
Take the semaphore n times, waiting forever.
Definition: sem.hpp:157
sem_base(sem_base &&)=delete
void reset() noexcept
Reset the semaphore counter to zero.
Definition: sem.hpp:107
void operator--(int) noexcept
Take the semaphore waiting forever.
Definition: sem.hpp:133
void operator++(int) noexcept
Give the semaphore.
Definition: sem.hpp:125
auto native_handle() noexcept -> native_pointer
get the native zephyr sem handle.
Definition: sem.hpp:171
sem_base & operator=(const sem_base &)=delete
sem_base(const sem_base &)=delete
struct k_sem native_type
Definition: sem.hpp:27
bool try_take_for(const std::chrono::duration< T_Rep, T_Period > &timeout_duration) noexcept
Try to take the semaphore waiting a certain timeout.
Definition: sem.hpp:86
constexpr static counter_type max_count
Maximum value of the counter.
Definition: sem.hpp:39
uint32_t counter_type
Type used as counter.
Definition: sem.hpp:34
constexpr sem_base() noexcept
Default constructor, only allowed derived objects.
Definition: sem.hpp:45
bool take() noexcept
Take the semaphore waiting forever.
Definition: sem.hpp:54
bool try_take() noexcept
Try to take the semaphore without waiting.
Definition: sem.hpp:68
native_type const * native_const_pointer
Definition: sem.hpp:29
counter_type count() noexcept
Get current semaphore count.
Definition: sem.hpp:117
A counting semaphore class borrowing the native sem.
Definition: sem.hpp:264
constexpr sem_ref & operator=(native_pointer s) noexcept
Assign a sem using a native k_sem*.
Definition: sem.hpp:299
constexpr sem_ref(T_Sem &s) noexcept
Construct a sem using a native k_sem*.
Definition: sem.hpp:285
constexpr sem_ref(native_pointer s) noexcept
Construct a sem using a native k_sem*.
Definition: sem.hpp:272
constexpr auto native_handle() noexcept -> native_pointer
get the native zephyr sem handle.
Definition: sem.hpp:327
constexpr sem_ref & operator=(T_Sem &s) noexcept
Assign a sem using another sem object.
Definition: sem.hpp:315
sem_ref()=delete
constexpr auto native_handle() const noexcept -> native_const_pointer
get the native zephyr sem handle.
Definition: sem.hpp:339
A counting semaphore class.
Definition: sem.hpp:196
sem & operator=(sem &&)=delete
sem(const sem &)=delete
constexpr auto native_handle() const noexcept -> native_const_pointer
get the native zephyr mutex handle.
Definition: sem.hpp:248
sem() noexcept
Default onstructor.
Definition: sem.hpp:228
sem(sem &&)=delete
sem(counter_type initial_count, counter_type count_limit) noexcept
Constructor initializing initial count and count limit.
Definition: sem.hpp:204
constexpr auto native_handle() noexcept -> native_pointer
get the native zephyr mutex handle.
Definition: sem.hpp:238
sem(counter_type initial_count) noexcept
Constructor initializing initial count.
Definition: sem.hpp:217
sem & operator=(const sem &)=delete
void yield() noexcept
Yield the current thread.
Definition: thread.hpp:50
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