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 <atomic>
19
20#ifdef CONFIG_OVE_SYNC
21
22namespace ove {
23
37class Mutex {
38public:
46#ifdef CONFIG_OVE_ZERO_HEAP
47 int err = ove_mutex_init(&handle_, &storage_);
48#else
49 int err = ove_mutex_create(&handle_);
50#endif
51 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
52 }
53
60 if (!handle_) return;
61#ifdef CONFIG_OVE_ZERO_HEAP
62 ove_mutex_deinit(handle_);
63#else
64 ove_mutex_destroy(handle_);
65#endif
66 }
67
68 Mutex(const Mutex &) = delete;
69 Mutex &operator=(const Mutex &) = delete;
70
71#ifdef CONFIG_OVE_ZERO_HEAP
72 Mutex(Mutex &&) = delete;
73 Mutex &operator=(Mutex &&) = delete;
74#else
79 Mutex(Mutex &&other) noexcept : handle_(other.handle_) {
80 other.handle_ = nullptr;
81 }
82
88 Mutex &operator=(Mutex &&other) noexcept {
89 if (this != &other) {
90 if (handle_) ove_mutex_destroy(handle_);
91 handle_ = other.handle_;
92 other.handle_ = nullptr;
93 }
94 return *this;
95 }
96#endif
97
104 [[nodiscard]] int lock(uint32_t timeout_ms = OVE_WAIT_FOREVER) {
105 return ove_mutex_lock(handle_, timeout_ms);
106 }
107
113 void unlock() {
114 ove_mutex_unlock(handle_);
115 }
116
121 bool valid() const { return handle_ != nullptr; }
122
127 ove_mutex_t handle() const { return handle_; }
128
129private:
130 ove_mutex_t handle_ = nullptr;
131#ifdef CONFIG_OVE_ZERO_HEAP
132 ove_mutex_storage_t storage_ = {};
133#endif
134};
135
147public:
155#ifdef CONFIG_OVE_ZERO_HEAP
156 int err = ove_recursive_mutex_init(&handle_, &storage_);
157#else
158 int err = ove_recursive_mutex_create(&handle_);
159#endif
160 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
161 }
162
167 if (!handle_) return;
168#ifdef CONFIG_OVE_ZERO_HEAP
169 ove_mutex_deinit(handle_);
170#else
171 ove_recursive_mutex_destroy(handle_);
172#endif
173 }
174
175 RecursiveMutex(const RecursiveMutex &) = delete;
176 RecursiveMutex &operator=(const RecursiveMutex &) = delete;
177
178#ifdef CONFIG_OVE_ZERO_HEAP
179 RecursiveMutex(RecursiveMutex &&) = delete;
180 RecursiveMutex &operator=(RecursiveMutex &&) = delete;
181#else
187 : handle_(other.handle_) {
188 other.handle_ = nullptr;
189 }
190
197 if (this != &other) {
198 if (handle_) ove_recursive_mutex_destroy(handle_);
199 handle_ = other.handle_;
200 other.handle_ = nullptr;
201 }
202 return *this;
203 }
204#endif
205
212 [[nodiscard]] int lock(uint32_t timeout_ms = OVE_WAIT_FOREVER) {
213 return ove_recursive_mutex_lock(handle_, timeout_ms);
214 }
215
219 void unlock() {
220 ove_recursive_mutex_unlock(handle_);
221 }
222
227 bool valid() const { return handle_ != nullptr; }
228
233 ove_mutex_t handle() const { return handle_; }
234
235private:
236 ove_mutex_t handle_ = nullptr;
237#ifdef CONFIG_OVE_ZERO_HEAP
238 ove_mutex_storage_t storage_ = {};
239#endif
240};
241
253public:
258 explicit LockGuard(Mutex &mtx)
259 : mtx_(mtx) {
260 (void)mtx_.lock(); /* wait forever — failure is fatal */
261 }
262
267 mtx_.unlock();
268 }
269
270 LockGuard(const LockGuard &) = delete;
271 LockGuard &operator=(const LockGuard &) = delete;
272 LockGuard(LockGuard &&) = delete;
273 LockGuard &operator=(LockGuard &&) = delete;
274
275private:
276 Mutex &mtx_;
277};
278
300template<typename T>
302public:
313 template<typename... Args>
314 T& init(Args&&... args) {
315 bool expected = false;
316 if (!initialized_.compare_exchange_strong(expected, true))
317 OVE_STATIC_INIT_ASSERT(false && "StaticCell already initialized");
318 return *new (storage_) T(std::forward<Args>(args)...);
319 }
320
328 T& get() {
329 OVE_STATIC_INIT_ASSERT(initialized_.load());
330 return *reinterpret_cast<T*>(storage_);
331 }
332
340 const T& get() const {
341 OVE_STATIC_INIT_ASSERT(initialized_.load());
342 return *reinterpret_cast<const T*>(storage_);
343 }
344
349 bool is_initialized() const { return initialized_.load(); }
350
351 StaticCell() = default;
352 ~StaticCell() = default;
353 StaticCell(const StaticCell&) = delete;
354 StaticCell& operator=(const StaticCell&) = delete;
355 StaticCell(StaticCell&&) = delete;
356 StaticCell& operator=(StaticCell&&) = delete;
357
358private:
359 alignas(T) uint8_t storage_[sizeof(T)]{};
360 std::atomic<bool> initialized_{false};
361};
362
379public:
387 explicit Semaphore(unsigned int initial = 0, unsigned int max = 1) {
388#ifdef CONFIG_OVE_ZERO_HEAP
389 int err = ove_sem_init(&handle_, &storage_, initial, max);
390#else
391 int err = ove_sem_create(&handle_, initial, max);
392#endif
393 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
394 }
395
400 if (!handle_) return;
401#ifdef CONFIG_OVE_ZERO_HEAP
402 ove_sem_deinit(handle_);
403#else
404 ove_sem_destroy(handle_);
405#endif
406 }
407
408 Semaphore(const Semaphore &) = delete;
409 Semaphore &operator=(const Semaphore &) = delete;
410
411#ifdef CONFIG_OVE_ZERO_HEAP
412 Semaphore(Semaphore &&) = delete;
413 Semaphore &operator=(Semaphore &&) = delete;
414#else
419 Semaphore(Semaphore &&other) noexcept : handle_(other.handle_) {
420 other.handle_ = nullptr;
421 }
422
428 Semaphore &operator=(Semaphore &&other) noexcept {
429 if (this != &other) {
430 if (handle_) ove_sem_destroy(handle_);
431 handle_ = other.handle_;
432 other.handle_ = nullptr;
433 }
434 return *this;
435 }
436#endif
437
444 [[nodiscard]] int take(uint32_t timeout_ms = OVE_WAIT_FOREVER) {
445 return ove_sem_take(handle_, timeout_ms);
446 }
447
453 void give() {
454 ove_sem_give(handle_);
455 }
456
461 bool valid() const { return handle_ != nullptr; }
462
467 ove_sem_t handle() const { return handle_; }
468
469private:
470 ove_sem_t handle_ = nullptr;
471#ifdef CONFIG_OVE_ZERO_HEAP
472 ove_sem_storage_t storage_ = {};
473#endif
474};
475
487class Event {
488public:
495#ifdef CONFIG_OVE_ZERO_HEAP
496 int err = ove_event_init(&handle_, &storage_);
497#else
498 int err = ove_event_create(&handle_);
499#endif
500 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
501 }
502
507 if (!handle_) return;
508#ifdef CONFIG_OVE_ZERO_HEAP
509 ove_event_deinit(handle_);
510#else
511 ove_event_destroy(handle_);
512#endif
513 }
514
515 Event(const Event &) = delete;
516 Event &operator=(const Event &) = delete;
517
518#ifdef CONFIG_OVE_ZERO_HEAP
519 Event(Event &&) = delete;
520 Event &operator=(Event &&) = delete;
521#else
526 Event(Event &&other) noexcept : handle_(other.handle_) {
527 other.handle_ = nullptr;
528 }
529
535 Event &operator=(Event &&other) noexcept {
536 if (this != &other) {
537 if (handle_) ove_event_destroy(handle_);
538 handle_ = other.handle_;
539 other.handle_ = nullptr;
540 }
541 return *this;
542 }
543#endif
544
551 [[nodiscard]] int wait(uint32_t timeout_ms = OVE_WAIT_FOREVER) {
552 return ove_event_wait(handle_, timeout_ms);
553 }
554
558 void signal() {
559 ove_event_signal(handle_);
560 }
561
568 ove_event_signal_from_isr(handle_);
569 }
570
575 bool valid() const { return handle_ != nullptr; }
576
581 ove_event_t handle() const { return handle_; }
582
583private:
584 ove_event_t handle_ = nullptr;
585#ifdef CONFIG_OVE_ZERO_HEAP
586 ove_event_storage_t storage_ = {};
587#endif
588};
589
603class CondVar {
604public:
611#ifdef CONFIG_OVE_ZERO_HEAP
612 int err = ove_condvar_init(&handle_, &storage_);
613#else
614 int err = ove_condvar_create(&handle_);
615#endif
616 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
617 }
618
623 if (!handle_) return;
624#ifdef CONFIG_OVE_ZERO_HEAP
625 ove_condvar_deinit(handle_);
626#else
627 ove_condvar_destroy(handle_);
628#endif
629 }
630
631 CondVar(const CondVar &) = delete;
632 CondVar &operator=(const CondVar &) = delete;
633
634#ifdef CONFIG_OVE_ZERO_HEAP
635 CondVar(CondVar &&) = delete;
636 CondVar &operator=(CondVar &&) = delete;
637#else
642 CondVar(CondVar &&other) noexcept : handle_(other.handle_) {
643 other.handle_ = nullptr;
644 }
645
651 CondVar &operator=(CondVar &&other) noexcept {
652 if (this != &other) {
653 if (handle_) ove_condvar_destroy(handle_);
654 handle_ = other.handle_;
655 other.handle_ = nullptr;
656 }
657 return *this;
658 }
659#endif
660
673 [[nodiscard]] int wait(Mutex &mtx,
674 uint32_t timeout_ms = OVE_WAIT_FOREVER) {
675 return ove_condvar_wait(handle_, mtx.handle(), timeout_ms);
676 }
677
681 void signal() {
682 ove_condvar_signal(handle_);
683 }
684
688 void broadcast() {
689 ove_condvar_broadcast(handle_);
690 }
691
696 bool valid() const { return handle_ != nullptr; }
697
702 ove_condvar_t handle() const { return handle_; }
703
704private:
705 ove_condvar_t handle_ = nullptr;
706#ifdef CONFIG_OVE_ZERO_HEAP
707 ove_condvar_storage_t storage_ = {};
708#endif
709};
710
711} // namespace ove
712
713#endif /* CONFIG_OVE_SYNC */
RAII wrapper around an oveRTOS condition variable.
Definition sync.hpp:603
int wait(Mutex &mtx, uint32_t timeout_ms=OVE_WAIT_FOREVER)
Atomically releases the mutex and waits for a notification.
Definition sync.hpp:673
CondVar & operator=(CondVar &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:651
~CondVar()
Destroys the condition variable, releasing the underlying kernel resource.
Definition sync.hpp:622
void signal()
Wakes one task waiting on this condition variable.
Definition sync.hpp:681
CondVar()
Constructs and initialises the condition variable.
Definition sync.hpp:610
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:696
CondVar(CondVar &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:642
ove_condvar_t handle() const
Returns the raw oveRTOS condition variable handle.
Definition sync.hpp:702
void broadcast()
Wakes all tasks waiting on this condition variable.
Definition sync.hpp:688
RAII wrapper around an oveRTOS binary event flag.
Definition sync.hpp:487
ove_event_t handle() const
Returns the raw oveRTOS event handle.
Definition sync.hpp:581
void signal_from_isr()
Signals the event from an ISR context, waking any blocked waiter.
Definition sync.hpp:567
Event(Event &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:526
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:575
int wait(uint32_t timeout_ms=OVE_WAIT_FOREVER)
Blocks the calling task until the event is signalled or the timeout expires.
Definition sync.hpp:551
~Event()
Destroys the event, releasing the underlying kernel resource.
Definition sync.hpp:506
Event()
Constructs and initialises the event in the unsignalled state.
Definition sync.hpp:494
Event & operator=(Event &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:535
void signal()
Signals the event from task context, waking any blocked waiter.
Definition sync.hpp:558
Scoped RAII guard that locks a Mutex on construction and unlocks it on destruction.
Definition sync.hpp:252
LockGuard(Mutex &mtx)
Constructs the guard, immediately locking the given mutex.
Definition sync.hpp:258
~LockGuard()
Destroys the guard, unlocking the associated mutex.
Definition sync.hpp:266
RAII wrapper around an oveRTOS non-recursive mutex.
Definition sync.hpp:37
Mutex(Mutex &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:79
ove_mutex_t handle() const
Returns the raw oveRTOS mutex handle.
Definition sync.hpp:127
int lock(uint32_t timeout_ms=OVE_WAIT_FOREVER)
Acquires the mutex, blocking until it is available or the timeout expires.
Definition sync.hpp:104
Mutex()
Constructs and initialises the mutex.
Definition sync.hpp:45
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:121
~Mutex()
Destroys the mutex, releasing the underlying kernel resource.
Definition sync.hpp:59
void unlock()
Releases the mutex.
Definition sync.hpp:113
Mutex & operator=(Mutex &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:88
RAII wrapper around an oveRTOS recursive mutex.
Definition sync.hpp:146
RecursiveMutex(RecursiveMutex &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:186
RecursiveMutex()
Constructs and initialises the recursive mutex.
Definition sync.hpp:154
void unlock()
Releases one level of the recursive lock.
Definition sync.hpp:219
int lock(uint32_t timeout_ms=OVE_WAIT_FOREVER)
Acquires the recursive mutex.
Definition sync.hpp:212
RecursiveMutex & operator=(RecursiveMutex &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:196
~RecursiveMutex()
Destroys the recursive mutex, releasing the underlying kernel resource.
Definition sync.hpp:166
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:227
ove_mutex_t handle() const
Returns the raw oveRTOS mutex handle.
Definition sync.hpp:233
RAII wrapper around an oveRTOS counting semaphore.
Definition sync.hpp:378
void give()
Increments the semaphore count, unblocking a waiting task if any.
Definition sync.hpp:453
ove_sem_t handle() const
Returns the raw oveRTOS semaphore handle.
Definition sync.hpp:467
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition sync.hpp:461
Semaphore & operator=(Semaphore &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition sync.hpp:428
int take(uint32_t timeout_ms=OVE_WAIT_FOREVER)
Decrements the semaphore count, blocking if the count is zero.
Definition sync.hpp:444
Semaphore(Semaphore &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition sync.hpp:419
~Semaphore()
Destroys the semaphore, releasing the underlying kernel resource.
Definition sync.hpp:399
Semaphore(unsigned int initial=0, unsigned int max=1)
Constructs and initialises the semaphore.
Definition sync.hpp:387
Thread-safe, lazily initialised storage cell for a single object of type T.
Definition sync.hpp:301
bool is_initialized() const
Returns true if init() has been called successfully.
Definition sync.hpp:349
T & init(Args &&... args)
Constructs the contained object in-place.
Definition sync.hpp:314
const T & get() const
Returns a const reference to the contained object.
Definition sync.hpp:340
T & get()
Returns a reference to the contained object.
Definition sync.hpp:328
Top-level namespace for all oveRTOS C++ abstractions.
Definition app.hpp:19
Common type definitions and concepts for the C++ wrapper layer.