oveRTOS C++ API
C++20 RAII wrappers for the oveRTOS C API
Loading...
Searching...
No Matches
sync.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 *
6 * This file is part of oveRTOS.
7 */
8
14#pragma once
15
16#include <ove/sync.h>
17#include <ove/types.hpp>
18#include <ove/error.hpp>
19#include <atomic>
20
21#ifdef CONFIG_OVE_SYNC
22
23namespace ove
24{
25
39class Mutex
40{
41 public:
49 {
50#ifdef CONFIG_OVE_ZERO_HEAP
51 int err = ove_mutex_init(&handle_, &storage_);
52#else
53 int err = ove_mutex_create(&handle_);
54#endif
55 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
56 }
57
63 ~Mutex() noexcept
64 {
65 if (!handle_)
66 return;
67#ifdef CONFIG_OVE_ZERO_HEAP
68 ove_mutex_deinit(handle_);
69#else
70 ove_mutex_destroy(handle_);
71#endif
72 }
73
74 Mutex(const Mutex &) = delete;
75 Mutex &operator=(const Mutex &) = delete;
76
77#ifdef CONFIG_OVE_ZERO_HEAP
78 Mutex(Mutex &&) = delete;
79 Mutex &operator=(Mutex &&) = delete;
80#else
85 Mutex(Mutex &&other) noexcept : handle_(other.handle_)
86 {
87 other.handle_ = nullptr;
88 }
89
95 Mutex &operator=(Mutex &&other) noexcept
96 {
97 if (this != &other) {
98 if (handle_)
99 ove_mutex_destroy(handle_);
100 handle_ = other.handle_;
101 other.handle_ = nullptr;
102 }
103 return *this;
104 }
105#endif
106
124 void lock()
125 {
126 const int err = ove_mutex_lock(handle_, OVE_WAIT_FOREVER);
127 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
128 }
129
135 [[nodiscard]] bool try_lock()
136 {
137 return ove_mutex_lock(handle_, 0) == OVE_OK;
138 }
139
157 template <class Rep, class Period>
158 [[nodiscard]] Result<void>
159 try_lock_for(const std::chrono::duration<Rep, Period> &rel) noexcept
160 {
161 return from_rc(ove_mutex_lock(handle_, to_timeout_ns(rel)));
162 }
163
176 template <class Clock, class Duration>
177 [[nodiscard]] Result<void>
178 try_lock_until(const std::chrono::time_point<Clock, Duration> &deadline) noexcept
179 {
180 const auto rel = deadline - Clock::now();
181 return from_rc(ove_mutex_lock(handle_, to_timeout_ns(rel)));
182 }
183
189 void unlock()
190 {
191 ove_mutex_unlock(handle_);
192 }
193
198 bool valid() const
199 {
200 return handle_ != nullptr;
201 }
202
207 ove_mutex_t handle() const
208 {
209 return handle_;
210 }
211
212 private:
213 ove_mutex_t handle_ = nullptr;
214#ifdef CONFIG_OVE_ZERO_HEAP
215 ove_mutex_storage_t storage_ = {};
216#endif
217};
218
219/* Regression guard. `BasicLockable` and `Lockable` are named
220 * requirements (not concepts) in the C++ standard; define equivalent
221 * local concepts and static_assert against them so a future change
222 * that breaks std-composition (e.g. removing `try_lock`) trips the
223 * build instead of failing far away in a user's `std::scoped_lock`
224 * instantiation. */
225namespace detail
226{
227
228template <class M>
229concept basic_lockable = requires(M m) {
230 { m.lock() };
231 { m.unlock() };
232};
233
234template <class M>
235concept lockable = basic_lockable<M> && requires(M m) {
236 { m.try_lock() } -> std::convertible_to<bool>;
237};
238
239} /* namespace detail */
240
242 "ove::Mutex must satisfy the BasicLockable named requirement");
243static_assert(detail::lockable<Mutex>, "ove::Mutex must satisfy the Lockable named requirement");
244
256{
257 public:
265 {
266#ifdef CONFIG_OVE_ZERO_HEAP
267 int err = ove_recursive_mutex_init(&handle_, &storage_);
268#else
269 int err = ove_recursive_mutex_create(&handle_);
270#endif
271 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
272 }
273
278 {
279 if (!handle_)
280 return;
281#ifdef CONFIG_OVE_ZERO_HEAP
282 ove_mutex_deinit(handle_);
283#else
284 ove_recursive_mutex_destroy(handle_);
285#endif
286 }
287
288 RecursiveMutex(const RecursiveMutex &) = delete;
289 RecursiveMutex &operator=(const RecursiveMutex &) = delete;
290
291#ifdef CONFIG_OVE_ZERO_HEAP
292 RecursiveMutex(RecursiveMutex &&) = delete;
293 RecursiveMutex &operator=(RecursiveMutex &&) = delete;
294#else
299 RecursiveMutex(RecursiveMutex &&other) noexcept : handle_(other.handle_)
300 {
301 other.handle_ = nullptr;
302 }
303
310 {
311 if (this != &other) {
312 if (handle_)
313 ove_recursive_mutex_destroy(handle_);
314 handle_ = other.handle_;
315 other.handle_ = nullptr;
316 }
317 return *this;
318 }
319#endif
320
326 void lock()
327 {
328 const int err = ove_recursive_mutex_lock(handle_, OVE_WAIT_FOREVER);
329 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
330 }
331
338 [[nodiscard]] bool try_lock()
339 {
340 return ove_recursive_mutex_lock(handle_, 0) == OVE_OK;
341 }
342
354 template <class Rep, class Period>
355 [[nodiscard]] Result<void>
356 try_lock_for(const std::chrono::duration<Rep, Period> &rel) noexcept
357 {
358 return from_rc(ove_recursive_mutex_lock(handle_, to_timeout_ns(rel)));
359 }
360
370 template <class Clock, class Duration>
371 [[nodiscard]] Result<void>
372 try_lock_until(const std::chrono::time_point<Clock, Duration> &deadline) noexcept
373 {
374 const auto rel = deadline - Clock::now();
375 return from_rc(ove_recursive_mutex_lock(handle_, to_timeout_ns(rel)));
376 }
377
381 void unlock()
382 {
383 ove_recursive_mutex_unlock(handle_);
384 }
385
390 bool valid() const
391 {
392 return handle_ != nullptr;
393 }
394
399 ove_mutex_t handle() const
400 {
401 return handle_;
402 }
403
404 private:
405 ove_mutex_t handle_ = nullptr;
406#ifdef CONFIG_OVE_ZERO_HEAP
407 ove_mutex_storage_t storage_ = {};
408#endif
409};
410
411static_assert(detail::basic_lockable<RecursiveMutex>,
412 "ove::RecursiveMutex must satisfy the BasicLockable named requirement");
413static_assert(detail::lockable<RecursiveMutex>,
414 "ove::RecursiveMutex must satisfy the Lockable named requirement");
415
427{
428 public:
444 explicit LockGuard(Mutex &mtx) : mtx_(mtx)
445 {
446 mtx_.lock();
447 }
448
452 ~LockGuard() noexcept
453 {
454 mtx_.unlock();
455 }
456
457 LockGuard(const LockGuard &) = delete;
458 LockGuard &operator=(const LockGuard &) = delete;
459 LockGuard(LockGuard &&) = delete;
460 LockGuard &operator=(LockGuard &&) = delete;
461
462 private:
463 Mutex &mtx_;
464};
465
492template <typename T> class StaticCell
493{
494 public:
505 template <typename... Args> T &init(Args &&...args)
506 {
507 bool expected = false;
508 if (!initialized_.compare_exchange_strong(expected, true))
509 OVE_STATIC_INIT_ASSERT(false && "StaticCell already initialized");
510 return *new (storage_) T(std::forward<Args>(args)...);
511 }
512
524 T &get()
525 {
526 OVE_STATIC_INIT_ASSERT(initialized_.load());
527 return *reinterpret_cast<T *>(storage_);
528 }
529
543 const T &get() const
544 {
545 OVE_STATIC_INIT_ASSERT(initialized_.load());
546 return *reinterpret_cast<const T *>(storage_);
547 }
548
553 bool is_initialized() const
554 {
555 return initialized_.load();
556 }
557
558 StaticCell() = default;
559 ~StaticCell() = default;
560 StaticCell(const StaticCell &) = delete;
561 StaticCell &operator=(const StaticCell &) = delete;
562 StaticCell(StaticCell &&) = delete;
563 StaticCell &operator=(StaticCell &&) = delete;
564
565 private:
566 alignas(T) uint8_t storage_[sizeof(T)]{};
567 std::atomic<bool> initialized_{false};
568};
569
586{
587 public:
595 explicit Semaphore(unsigned int initial = 0, unsigned int max = 1)
596 {
597#ifdef CONFIG_OVE_ZERO_HEAP
598 int err = ove_sem_init(&handle_, &storage_, initial, max);
599#else
600 int err = ove_sem_create(&handle_, initial, max);
601#endif
602 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
603 }
604
608 ~Semaphore() noexcept
609 {
610 if (!handle_)
611 return;
612#ifdef CONFIG_OVE_ZERO_HEAP
613 ove_sem_deinit(handle_);
614#else
615 ove_sem_destroy(handle_);
616#endif
617 }
618
619 Semaphore(const Semaphore &) = delete;
620 Semaphore &operator=(const Semaphore &) = delete;
621
622#ifdef CONFIG_OVE_ZERO_HEAP
623 Semaphore(Semaphore &&) = delete;
624 Semaphore &operator=(Semaphore &&) = delete;
625#else
630 Semaphore(Semaphore &&other) noexcept : handle_(other.handle_)
631 {
632 other.handle_ = nullptr;
633 }
634
640 Semaphore &operator=(Semaphore &&other) noexcept
641 {
642 if (this != &other) {
643 if (handle_)
644 ove_sem_destroy(handle_);
645 handle_ = other.handle_;
646 other.handle_ = nullptr;
647 }
648 return *this;
649 }
650#endif
651
660 void acquire()
661 {
662 const int err = ove_sem_take(handle_, OVE_WAIT_FOREVER);
663 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
664 }
665
670 [[nodiscard]] bool try_acquire()
671 {
672 return ove_sem_take(handle_, 0) == OVE_OK;
673 }
674
692 template <class Rep, class Period>
693 [[nodiscard]] Result<void>
694 try_acquire_for(const std::chrono::duration<Rep, Period> &rel) noexcept
695 {
696 return from_rc(ove_sem_take(handle_, to_timeout_ns(rel)));
697 }
698
709 template <class Clock, class Duration>
710 [[nodiscard]] Result<void>
711 try_acquire_until(const std::chrono::time_point<Clock, Duration> &deadline) noexcept
712 {
713 const auto rel = deadline - Clock::now();
714 return from_rc(ove_sem_take(handle_, to_timeout_ns(rel)));
715 }
716
725 void release()
726 {
727 ove_sem_give(handle_);
728 }
729
734 bool valid() const
735 {
736 return handle_ != nullptr;
737 }
738
743 ove_sem_t handle() const
744 {
745 return handle_;
746 }
747
748 private:
749 ove_sem_t handle_ = nullptr;
750#ifdef CONFIG_OVE_ZERO_HEAP
751 ove_sem_storage_t storage_ = {};
752#endif
753};
754
766class Event
767{
768 public:
775 {
776#ifdef CONFIG_OVE_ZERO_HEAP
777 int err = ove_event_init(&handle_, &storage_);
778#else
779 int err = ove_event_create(&handle_);
780#endif
781 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
782 }
783
787 ~Event() noexcept
788 {
789 if (!handle_)
790 return;
791#ifdef CONFIG_OVE_ZERO_HEAP
792 ove_event_deinit(handle_);
793#else
794 ove_event_destroy(handle_);
795#endif
796 }
797
798 Event(const Event &) = delete;
799 Event &operator=(const Event &) = delete;
800
801#ifdef CONFIG_OVE_ZERO_HEAP
802 Event(Event &&) = delete;
803 Event &operator=(Event &&) = delete;
804#else
809 Event(Event &&other) noexcept : handle_(other.handle_)
810 {
811 other.handle_ = nullptr;
812 }
813
819 Event &operator=(Event &&other) noexcept
820 {
821 if (this != &other) {
822 if (handle_)
823 ove_event_destroy(handle_);
824 handle_ = other.handle_;
825 other.handle_ = nullptr;
826 }
827 return *this;
828 }
829#endif
830
838 void wait()
839 {
840 const int err = ove_event_wait(handle_, OVE_WAIT_FOREVER);
841 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
842 }
843
849 [[nodiscard]] bool try_wait()
850 {
851 return ove_event_wait(handle_, 0) == OVE_OK;
852 }
853
863 template <class Rep, class Period>
864 [[nodiscard]] Result<void>
865 try_wait_for(const std::chrono::duration<Rep, Period> &rel) noexcept
866 {
867 return from_rc(ove_event_wait(handle_, to_timeout_ns(rel)));
868 }
869
878 template <class Clock, class Duration>
879 [[nodiscard]] Result<void>
880 try_wait_until(const std::chrono::time_point<Clock, Duration> &deadline) noexcept
881 {
882 const auto rel = deadline - Clock::now();
883 return from_rc(ove_event_wait(handle_, to_timeout_ns(rel)));
884 }
885
889 void signal()
890 {
891 ove_event_signal(handle_);
892 }
893
900 {
901 ove_event_signal_from_isr(handle_);
902 }
903
908 bool valid() const
909 {
910 return handle_ != nullptr;
911 }
912
917 ove_event_t handle() const
918 {
919 return handle_;
920 }
921
922 private:
923 ove_event_t handle_ = nullptr;
924#ifdef CONFIG_OVE_ZERO_HEAP
925 ove_event_storage_t storage_ = {};
926#endif
927};
928
943{
944 public:
951 {
952#ifdef CONFIG_OVE_ZERO_HEAP
953 int err = ove_condvar_init(&handle_, &storage_);
954#else
955 int err = ove_condvar_create(&handle_);
956#endif
957 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
958 }
959
963 ~CondVar() noexcept
964 {
965 if (!handle_)
966 return;
967#ifdef CONFIG_OVE_ZERO_HEAP
968 ove_condvar_deinit(handle_);
969#else
970 ove_condvar_destroy(handle_);
971#endif
972 }
973
974 CondVar(const CondVar &) = delete;
975 CondVar &operator=(const CondVar &) = delete;
976
977#ifdef CONFIG_OVE_ZERO_HEAP
978 CondVar(CondVar &&) = delete;
979 CondVar &operator=(CondVar &&) = delete;
980#else
985 CondVar(CondVar &&other) noexcept : handle_(other.handle_)
986 {
987 other.handle_ = nullptr;
988 }
989
995 CondVar &operator=(CondVar &&other) noexcept
996 {
997 if (this != &other) {
998 if (handle_)
999 ove_condvar_destroy(handle_);
1000 handle_ = other.handle_;
1001 other.handle_ = nullptr;
1002 }
1003 return *this;
1004 }
1005#endif
1006
1023 void wait(Mutex &mtx)
1024 {
1025 const int err = ove_condvar_wait(handle_, mtx.handle(), OVE_WAIT_FOREVER);
1026 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
1027 }
1028
1059 template <class Rep, class Period>
1060 [[nodiscard]] Result<void>
1061 try_wait_for(Mutex &mtx, const std::chrono::duration<Rep, Period> &rel) noexcept
1062 {
1063 return from_rc(ove_condvar_wait(handle_, mtx.handle(), to_timeout_ns(rel)));
1064 }
1065
1074 template <class Clock, class Duration>
1075 [[nodiscard]] Result<void>
1077 const std::chrono::time_point<Clock, Duration> &deadline) noexcept
1078 {
1079 const auto rel = deadline - Clock::now();
1080 return from_rc(ove_condvar_wait(handle_, mtx.handle(), to_timeout_ns(rel)));
1081 }
1082
1098 template <typename Predicate> void wait(Mutex &mtx, Predicate pred)
1099 {
1100 while (!pred()) {
1101 wait(mtx);
1102 }
1103 }
1104
1115 template <typename Rep, typename Period, typename Predicate>
1116 [[nodiscard]] bool try_wait_for(Mutex &mtx, std::chrono::duration<Rep, Period> rel,
1117 Predicate pred)
1118 {
1119 const auto deadline = steady_clock::now() + rel;
1120 return try_wait_until(mtx, deadline, pred);
1121 }
1122
1134 template <typename Clock, typename Duration, typename Predicate>
1135 [[nodiscard]] bool try_wait_until(Mutex &mtx,
1136 const std::chrono::time_point<Clock, Duration> &deadline,
1137 Predicate pred)
1138 {
1139 while (!pred()) {
1140 const auto now = Clock::now();
1141 if (now >= deadline)
1142 return pred();
1143 const int rc = ove_condvar_wait(handle_, mtx.handle(),
1144 to_timeout_ns(deadline - now));
1145 (void)rc; /* spurious wake-up or timeout — re-check pred */
1146 }
1147 return true;
1148 }
1149
1155 {
1156 ove_condvar_signal(handle_);
1157 }
1158
1164 {
1165 ove_condvar_broadcast(handle_);
1166 }
1167
1172 bool valid() const
1173 {
1174 return handle_ != nullptr;
1175 }
1176
1181 ove_condvar_t handle() const
1182 {
1183 return handle_;
1184 }
1185
1186 private:
1187 ove_condvar_t handle_ = nullptr;
1188#ifdef CONFIG_OVE_ZERO_HEAP
1189 ove_condvar_storage_t storage_ = {};
1190#endif
1191};
1192
1193} // namespace ove
1194
1195#endif /* CONFIG_OVE_SYNC */
RAII wrapper around an oveRTOS condition variable.
Definition sync.hpp:943
Result< void > try_wait_until(Mutex &mtx, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Deadline-based wait templated over the clock.
Definition sync.hpp:1076
CondVar & operator=(CondVar &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:995
void wait(Mutex &mtx)
Atomically releases the mutex and waits for a notification.
Definition sync.hpp:1023
bool try_wait_until(Mutex &mtx, const std::chrono::time_point< Clock, Duration > &deadline, Predicate pred)
Deadline-based wait with predicate. std::condition_variable::wait_until predicate-overload analog.
Definition sync.hpp:1135
void wait(Mutex &mtx, Predicate pred)
Predicate-loop wait. std::condition_variable::wait predicate-overload analog.
Definition sync.hpp:1098
Result< void > try_wait_for(Mutex &mtx, const std::chrono::duration< Rep, Period > &rel) noexcept
Bounded-wait.
Definition sync.hpp:1061
CondVar()
Constructs and initialises the condition variable.
Definition sync.hpp:950
void notify_all()
Wakes all tasks waiting on this condition variable. std::condition_variable::notify_all analog.
Definition sync.hpp:1163
bool try_wait_for(Mutex &mtx, std::chrono::duration< Rep, Period > rel, Predicate pred)
Bounded-wait with predicate. std::condition_variable::wait_for predicate-overload analog.
Definition sync.hpp:1116
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:1172
~CondVar() noexcept
Destroys the condition variable, releasing the underlying kernel resource.
Definition sync.hpp:963
CondVar(CondVar &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:985
void notify_one()
Wakes one task waiting on this condition variable. std::condition_variable::notify_one analog.
Definition sync.hpp:1154
ove_condvar_t handle() const
Returns the raw oveRTOS condition variable handle.
Definition sync.hpp:1181
RAII wrapper around an oveRTOS binary event flag.
Definition sync.hpp:767
ove_event_t handle() const
Returns the raw oveRTOS event handle.
Definition sync.hpp:917
void signal_from_isr()
Signals the event from an ISR context, waking any blocked waiter.
Definition sync.hpp:899
Event(Event &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:809
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:908
~Event() noexcept
Destroys the event, releasing the underlying kernel resource.
Definition sync.hpp:787
Event()
Constructs and initialises the event in the unsignalled state.
Definition sync.hpp:774
void wait()
Blocks the calling task until the event is signalled.
Definition sync.hpp:838
Event & operator=(Event &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:819
Result< void > try_wait_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Deadline-based wait templated over the clock.
Definition sync.hpp:880
Result< void > try_wait_for(const std::chrono::duration< Rep, Period > &rel) noexcept
Bounded-wait.
Definition sync.hpp:865
bool try_wait()
Non-blocking check.
Definition sync.hpp:849
void signal()
Signals the event from task context, waking any blocked waiter.
Definition sync.hpp:889
Scoped RAII guard that locks a Mutex on construction and unlocks it on destruction.
Definition sync.hpp:427
LockGuard(Mutex &mtx)
Constructs the guard, immediately locking the given mutex.
Definition sync.hpp:444
~LockGuard() noexcept
Destroys the guard, unlocking the associated mutex.
Definition sync.hpp:452
RAII wrapper around an oveRTOS non-recursive mutex.
Definition sync.hpp:40
Mutex(Mutex &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:85
bool try_lock()
Attempts to acquire the mutex without blocking. Satisfies the Lockable named requirement (alongside l...
Definition sync.hpp:135
ove_mutex_t handle() const
Returns the raw oveRTOS mutex handle.
Definition sync.hpp:207
~Mutex() noexcept
Destroys the mutex, releasing the underlying kernel resource.
Definition sync.hpp:63
Mutex()
Constructs and initialises the mutex.
Definition sync.hpp:48
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:198
void unlock()
Releases the mutex.
Definition sync.hpp:189
Mutex & operator=(Mutex &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:95
Result< void > try_lock_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Attempts to acquire the mutex by deadline.
Definition sync.hpp:178
Result< void > try_lock_for(const std::chrono::duration< Rep, Period > &rel) noexcept
Attempts to acquire the mutex within rel.
Definition sync.hpp:159
void lock()
Acquires the mutex, blocking indefinitely. std::mutex::lock analog.
Definition sync.hpp:124
RAII wrapper around an oveRTOS recursive mutex.
Definition sync.hpp:256
RecursiveMutex(RecursiveMutex &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:299
Result< void > try_lock_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Deadline-based acquisition templated over the clock.
Definition sync.hpp:372
RecursiveMutex()
Constructs and initialises the recursive mutex.
Definition sync.hpp:264
void unlock()
Releases one level of the recursive lock.
Definition sync.hpp:381
~RecursiveMutex() noexcept
Destroys the recursive mutex, releasing the underlying kernel resource.
Definition sync.hpp:277
bool try_lock()
Non-blocking acquisition attempt. Part of the Lockable named requirement satisfied by this class.
Definition sync.hpp:338
Result< void > try_lock_for(const std::chrono::duration< Rep, Period > &rel) noexcept
Bounded-wait acquisition. Same shape as Mutex::try_lock_for — see that method for the TimedLockable n...
Definition sync.hpp:356
RecursiveMutex & operator=(RecursiveMutex &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:309
void lock()
Acquires the recursive mutex, blocking indefinitely.
Definition sync.hpp:326
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:390
ove_mutex_t handle() const
Returns the raw oveRTOS mutex handle.
Definition sync.hpp:399
RAII wrapper around an oveRTOS counting semaphore.
Definition sync.hpp:586
ove_sem_t handle() const
Returns the raw oveRTOS semaphore handle.
Definition sync.hpp:743
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:734
Result< void > try_acquire_for(const std::chrono::duration< Rep, Period > &rel) noexcept
Bounded-wait acquisition.
Definition sync.hpp:694
void release()
Increments the semaphore count, unblocking a waiting task if any.
Definition sync.hpp:725
bool try_acquire()
Non-blocking acquisition attempt. std::counting_semaphore::try_acquire analog.
Definition sync.hpp:670
void acquire()
Decrements the semaphore count, blocking indefinitely.
Definition sync.hpp:660
Result< void > try_acquire_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Deadline-based acquisition templated over the clock.
Definition sync.hpp:711
Semaphore & operator=(Semaphore &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:640
Semaphore(Semaphore &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:630
~Semaphore() noexcept
Destroys the semaphore, releasing the underlying kernel resource.
Definition sync.hpp:608
Semaphore(unsigned int initial=0, unsigned int max=1)
Constructs and initialises the semaphore.
Definition sync.hpp:595
Thread-safe, lazily initialised storage cell for a single object of type T.
Definition sync.hpp:493
bool is_initialized() const
Returns true if init() has been called successfully.
Definition sync.hpp:553
T & init(Args &&...args)
Constructs the contained object in-place.
Definition sync.hpp:505
const T & get() const
Returns a const reference to the contained object.
Definition sync.hpp:543
T & get()
Returns a reference to the contained object.
Definition sync.hpp:524
Definition sync.hpp:229
Definition sync.hpp:235
Strong ove::Error type, Result<T> alias, and std::error_code interop for the oveRTOS C++ binding.
Top-level namespace for all oveRTOS C++ abstractions.
Definition app.hpp:20
constexpr uint64_t to_timeout_ns(std::chrono::duration< Rep, Period > d) noexcept
Convert a chrono duration to uint64_t nanoseconds for the C API.
Definition types.hpp:129
Result< void > from_rc(int rc) noexcept
Lifts a substrate rc-code into a Result<void>.
Definition error.hpp:254
std::expected< T, Error > Result
std::expected-based result alias.
Definition error.hpp:139
Common type definitions and concepts for the C++ wrapper layer.