oveRTOS C++ API
C++20 RAII wrappers for the oveRTOS C API
Loading...
Searching...
No Matches
queue.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/queue.h>
17#include <ove/types.hpp>
18#include <ove/error.hpp>
19
20#include <type_traits>
21
22#ifdef CONFIG_OVE_QUEUE
23
24namespace ove
25{
26
46template <typename T, size_t MaxItems = 0> class Queue
47{
48 static_assert(std::is_trivially_copyable_v<T>,
49 "ove::Queue<T, N> requires T to be trivially copyable. "
50 "The substrate memcpy()s items of sizeof(T) bytes — non-trivial "
51 "types (std::string, std::vector, std::unique_ptr, user types with "
52 "explicit copy/move ctors or destructors that do bookkeeping) corrupt "
53 "their internal state on memcpy. Wrap them in a smart pointer or "
54 "POD struct, or transfer ownership by pointer through the queue.");
55
56 public:
64 requires(MaxItems > 0)
65 {
66#ifdef CONFIG_OVE_ZERO_HEAP
67 static_assert(MaxItems > 0, "MaxItems must be > 0 in zero-heap mode");
68 int err = ove_queue_init(&handle_, &storage_, buffer_, sizeof(T), MaxItems);
69#else
70 int err = ove_queue_create(&handle_, sizeof(T), MaxItems);
71#endif
72 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
73 }
74
78 ~Queue() noexcept
79 {
80 if (!handle_)
81 return;
82#ifdef CONFIG_OVE_ZERO_HEAP
83 ove_queue_deinit(handle_);
84#else
85 ove_queue_destroy(handle_);
86#endif
87 }
88
89 Queue(const Queue &) = delete;
90 Queue &operator=(const Queue &) = delete;
91
92#ifdef CONFIG_OVE_ZERO_HEAP
93 Queue(Queue &&) = delete;
94 Queue &operator=(Queue &&) = delete;
95#else
100 Queue(Queue &&other) noexcept : handle_(other.handle_)
101 {
102 other.handle_ = nullptr;
103 }
104
110 Queue &operator=(Queue &&other) noexcept
111 {
112 if (this != &other) {
113 if (handle_)
114 ove_queue_destroy(handle_);
115 handle_ = other.handle_;
116 other.handle_ = nullptr;
117 }
118 return *this;
119 }
120#endif
121
129 void send(const T &item)
130 {
131 const int err = ove_queue_send(handle_, &item, OVE_WAIT_FOREVER);
132 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
133 }
134
139 [[nodiscard]] bool try_send(const T &item)
140 {
141 return ove_queue_send(handle_, &item, 0) == OVE_OK;
142 }
143
154 template <class Rep, class Period>
155 [[nodiscard]] Result<void>
156 try_send_for(const T &item, const std::chrono::duration<Rep, Period> &rel) noexcept
157 {
158 return from_rc(ove_queue_send(handle_, &item, to_timeout_ns(rel)));
159 }
160
168 template <class Clock, class Duration>
169 [[nodiscard]] Result<void>
170 try_send_until(const T &item,
171 const std::chrono::time_point<Clock, Duration> &deadline) noexcept
172 {
173 const auto rel = deadline - Clock::now();
174 return from_rc(ove_queue_send(handle_, &item, to_timeout_ns(rel)));
175 }
176
185 void receive(T &out)
186 {
187 const int err = ove_queue_receive(handle_, &out, OVE_WAIT_FOREVER);
188 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
189 }
190
195 [[nodiscard]] bool try_receive(T &out)
196 {
197 return ove_queue_receive(handle_, &out, 0) == OVE_OK;
198 }
199
211 template <class Rep, class Period>
212 [[nodiscard]] Result<void>
213 try_receive_for(T &out, const std::chrono::duration<Rep, Period> &rel) noexcept
214 {
215 return from_rc(ove_queue_receive(handle_, &out, to_timeout_ns(rel)));
216 }
217
223 template <class Clock, class Duration>
224 [[nodiscard]] Result<void>
225 try_receive_until(T &out, const std::chrono::time_point<Clock, Duration> &deadline) noexcept
226 {
227 const auto rel = deadline - Clock::now();
228 return from_rc(ove_queue_receive(handle_, &out, to_timeout_ns(rel)));
229 }
230
239 [[nodiscard]] Result<void> send_from_isr(const T &item) noexcept
240 {
241 return from_rc(ove_queue_send_from_isr(handle_, &item));
242 }
243
252 [[nodiscard]] Result<void> receive_from_isr(T &out) noexcept
253 {
254 return from_rc(ove_queue_receive_from_isr(handle_, &out));
255 }
256
261 bool valid() const
262 {
263 return handle_ != nullptr;
264 }
265
270 ove_queue_t handle() const
271 {
272 return handle_;
273 }
274
275 private:
276 ove_queue_t handle_ = nullptr;
277#ifdef CONFIG_OVE_ZERO_HEAP
278 /* `buffer_` precedes `storage_` so the latter (whose underlying C
279 * struct ends in a flexible-array `inline_storage[]`) sits at the
280 * end of the C++ class. C99 allows FAMs anywhere in a struct, but
281 * C++ rejects another member after one — see
282 * backends/freertos/include/ove_storage_freertos.h FAM commentary. */
283 T buffer_[MaxItems > 0 ? MaxItems : 1];
284 ove_queue_storage_t storage_ = {};
285#endif
286};
287
288} // namespace ove
289
290#endif /* CONFIG_OVE_QUEUE */
RAII wrapper around an oveRTOS typed message queue.
Definition queue.hpp:47
ove_queue_t handle() const
Returns the raw oveRTOS queue handle.
Definition queue.hpp:270
Queue()
Constructs and initialises the queue.
Definition queue.hpp:63
~Queue() noexcept
Destroys the queue, releasing the underlying kernel resource.
Definition queue.hpp:78
void receive(T &out)
Receives an item from the front of the queue, blocking indefinitely.
Definition queue.hpp:185
void send(const T &item)
Sends an item to the back of the queue, blocking indefinitely.
Definition queue.hpp:129
Queue & operator=(Queue &&other) noexcept
Move-assignment operator — transfers ownership of the kernel handle.
Definition queue.hpp:110
Queue(Queue &&other) noexcept
Move constructor — transfers ownership of the kernel handle.
Definition queue.hpp:100
Result< void > receive_from_isr(T &out) noexcept
Receives an item from the queue from an ISR context (non-blocking).
Definition queue.hpp:252
Result< void > send_from_isr(const T &item) noexcept
Sends an item to the queue from an ISR context (non-blocking).
Definition queue.hpp:239
Result< void > try_receive_for(T &out, const std::chrono::duration< Rep, Period > &rel) noexcept
Bounded-wait receive.
Definition queue.hpp:213
Result< void > try_send_for(const T &item, const std::chrono::duration< Rep, Period > &rel) noexcept
Bounded-wait send.
Definition queue.hpp:156
Result< void > try_send_until(const T &item, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Deadline-based send templated over the clock. See Mutex::try_lock_until for the templated-clock ratio...
Definition queue.hpp:170
bool try_send(const T &item)
Non-blocking send.
Definition queue.hpp:139
bool try_receive(T &out)
Non-blocking receive.
Definition queue.hpp:195
Result< void > try_receive_until(T &out, const std::chrono::time_point< Clock, Duration > &deadline) noexcept
Deadline-based receive templated over the clock.
Definition queue.hpp:225
bool valid() const
Returns true if the underlying kernel handle is non-null.
Definition queue.hpp:261
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.