22#include <idfxx/chrono>
24#include <idfxx/memory>
29#include <freertos/FreeRTOS.h>
30#include <freertos/idf_additions.h>
31#include <freertos/queue.h>
66 requires std::is_trivially_copyable_v<T>
69#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
84 _handle = xQueueCreateWithCaps(length,
sizeof(T),
to_underlying(mem_caps));
85 if (_handle ==
nullptr) {
105 q._handle = xQueueCreateWithCaps(length,
sizeof(T),
to_underlying(mem_caps));
106 if (q._handle ==
nullptr) {
118 if (_handle !=
nullptr) {
119 vQueueDeleteWithCaps(_handle);
128 : _handle(std::exchange(other._handle,
nullptr)) {}
132 if (
this != &other) {
133 if (_handle !=
nullptr) {
134 vQueueDeleteWithCaps(_handle);
136 _handle = std::exchange(other._handle,
nullptr);
145#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
170 template<
typename Rep,
typename Period>
171 void send(
const T& item,
const std::chrono::duration<Rep, Period>&
timeout) {
188 template<
typename Clock,
typename Duration>
189 void send_until(
const T& item,
const std::chrono::time_point<Clock, Duration>& deadline) {
219 template<
typename Rep,
typename Period>
238 template<
typename Clock,
typename Duration>
267 template<
typename Rep,
typename Period>
284 template<
typename Clock,
typename Duration>
286 auto remaining = deadline - Clock::now();
287 if (remaining <=
decltype(remaining)::zero()) {
288 return _try_send(item, 0);
318 template<
typename Rep,
typename Period>
336 template<
typename Clock,
typename Duration>
339 auto remaining = deadline - Clock::now();
340 if (remaining <=
decltype(remaining)::zero()) {
341 return _try_send_to_front(item, 0);
362 if (_handle ==
nullptr) {
365 xQueueOverwrite(_handle, &item);
372#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
397 template<
typename Rep,
typename Period>
415 template<
typename Clock,
typename Duration>
442 template<
typename Rep,
typename Period>
458 template<
typename Clock,
typename Duration>
460 auto remaining = deadline - Clock::now();
461 if (remaining <=
decltype(remaining)::zero()) {
462 return _try_receive(0);
471#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
497 template<
typename Rep,
typename Period>
498 [[nodiscard]] T
peek(
const std::chrono::duration<Rep, Period>&
timeout) {
516 template<
typename Clock,
typename Duration>
517 [[nodiscard]] T
peek_until(
const std::chrono::time_point<Clock, Duration>& deadline) {
544 template<
typename Rep,
typename Period>
561 template<
typename Clock,
typename Duration>
563 auto remaining = deadline - Clock::now();
564 if (remaining <=
decltype(remaining)::zero()) {
610 if (_handle ==
nullptr) {
611 return {
false,
false};
613 BaseType_t woken = pdFALSE;
614 BaseType_t ret = xQueueSendFromISR(_handle, &item, &woken);
615 return {ret == pdTRUE, woken == pdTRUE};
636 if (_handle ==
nullptr) {
637 return {
false,
false};
639 BaseType_t woken = pdFALSE;
640 BaseType_t ret = xQueueSendToFrontFromISR(_handle, &item, &woken);
641 return {ret == pdTRUE, woken == pdTRUE};
664 if (_handle ==
nullptr) {
667 BaseType_t woken = pdFALSE;
668 xQueueOverwriteFromISR(_handle, &item, &woken);
669 return woken == pdTRUE;
692 if (_handle ==
nullptr) {
693 return {std::nullopt,
false};
696 BaseType_t woken = pdFALSE;
697 if (xQueueReceiveFromISR(_handle, &item, &woken) == pdTRUE) {
698 return {item, woken == pdTRUE};
700 return {std::nullopt, woken == pdTRUE};
717 if (_handle ==
nullptr) {
721 if (xQueuePeekFromISR(_handle, &item) == pdTRUE) {
736 [[nodiscard]]
size_t size() const noexcept {
737 if (_handle ==
nullptr) {
740 return uxQueueMessagesWaiting(_handle);
749 if (_handle ==
nullptr) {
752 return uxQueueSpacesAvailable(_handle);
760 [[nodiscard]]
bool empty() const noexcept {
761 if (_handle ==
nullptr) {
764 return uxQueueMessagesWaiting(_handle) == 0;
772 [[nodiscard]]
bool full() const noexcept {
773 if (_handle ==
nullptr) {
776 return uxQueueSpacesAvailable(_handle) == 0;
787 [[nodiscard]] QueueHandle_t
idf_handle() const noexcept {
return _handle; }
795 if (_handle ==
nullptr) {
798 xQueueReset(_handle);
803 : _handle(
nullptr) {}
805 [[nodiscard]] result<void> _try_send(
const T& item, TickType_t ticks) {
806 if (_handle ==
nullptr) {
809 if (xQueueSend(_handle, &item, ticks) != pdTRUE) {
815 [[nodiscard]] result<void> _try_send_to_front(
const T& item, TickType_t ticks) {
816 if (_handle ==
nullptr) {
819 if (xQueueSendToFront(_handle, &item, ticks) != pdTRUE) {
825 [[nodiscard]] result<T> _try_receive(TickType_t ticks) {
826 if (_handle ==
nullptr) {
830 if (xQueueReceive(_handle, &item, ticks) != pdTRUE) {
836 [[nodiscard]] result<T> _try_peek(TickType_t ticks) {
837 if (_handle ==
nullptr) {
841 if (xQueuePeek(_handle, &item, ticks) != pdTRUE) {
847 QueueHandle_t _handle =
nullptr;
Type-safe set of flags from a scoped enum.
Type-safe inter-task message queue.
void send_to_front(const T &item, const std::chrono::duration< Rep, Period > &timeout)
Sends an item to the front of the queue with a timeout.
T peek_until(const std::chrono::time_point< Clock, Duration > &deadline)
Peeks at the front item in the queue without removing it, with a deadline.
size_t size() const noexcept
Returns the number of items currently in the queue.
void send_to_front_until(const T &item, const std::chrono::time_point< Clock, Duration > &deadline)
Sends an item to the front of the queue with a deadline.
queue & operator=(const queue &)=delete
bool empty() const noexcept
Checks if the queue is empty.
T peek(const std::chrono::duration< Rep, Period > &timeout)
Peeks at the front item in the queue without removing it, with a timeout.
bool full() const noexcept
Checks if the queue is full.
result< void > try_send_to_front_until(const T &item, const std::chrono::time_point< Clock, Duration > &deadline)
Sends an item to the front of the queue with a deadline.
isr_send_result IRAM_ATTR send_to_front_from_isr(const T &item) noexcept
Sends an item to the front of the queue from ISR context.
result< T > try_peek_until(const std::chrono::time_point< Clock, Duration > &deadline)
Peeks at the front item in the queue without removing it, with a deadline.
T receive()
Receives an item from the queue, blocking indefinitely.
void send_to_front(const T &item)
Sends an item to the front of the queue, blocking indefinitely.
void reset() noexcept
Removes all items from the queue.
void send(const T &item)
Sends an item to the back of the queue, blocking indefinitely.
~queue()
Destroys the queue and releases all resources.
queue(const queue &)=delete
result< void > try_send(const T &item)
Sends an item to the back of the queue, blocking indefinitely.
size_t available() const noexcept
Returns the number of free spaces in the queue.
result< void > try_send_to_front(const T &item)
Sends an item to the front of the queue, blocking indefinitely.
queue(queue &&other) noexcept
Move constructor.
result< T > try_peek(const std::chrono::duration< Rep, Period > &timeout)
Peeks at the front item in the queue without removing it, with a timeout.
std::optional< T > IRAM_ATTR peek_from_isr() const noexcept
Peeks at the front item in the queue from ISR context without removing it.
T receive_until(const std::chrono::time_point< Clock, Duration > &deadline)
Receives an item from the queue with a deadline.
QueueHandle_t idf_handle() const noexcept
Returns the underlying FreeRTOS queue handle.
queue & operator=(queue &&other) noexcept
Move assignment.
isr_receive_result IRAM_ATTR receive_from_isr() noexcept
Receives an item from the queue in ISR context.
result< void > try_send(const T &item, const std::chrono::duration< Rep, Period > &timeout)
Sends an item to the back of the queue with a timeout.
queue(size_t length, flags< memory::capabilities > mem_caps=memory::capabilities::dram)
Creates a queue with the specified capacity.
result< void > try_send_to_front(const T &item, const std::chrono::duration< Rep, Period > &timeout)
Sends an item to the front of the queue with a timeout.
void send_until(const T &item, const std::chrono::time_point< Clock, Duration > &deadline)
Sends an item to the back of the queue with a deadline.
result< T > try_receive()
Receives an item from the queue, blocking indefinitely.
T peek()
Peeks at the front item in the queue without removing it, blocking indefinitely.
result< T > try_receive(const std::chrono::duration< Rep, Period > &timeout)
Receives an item from the queue with a timeout.
bool IRAM_ATTR overwrite_from_isr(const T &item) noexcept
Overwrites the last item in the queue from ISR context.
isr_send_result IRAM_ATTR send_from_isr(const T &item) noexcept
Sends an item to the back of the queue from ISR context.
result< T > try_peek()
Peeks at the front item in the queue without removing it, blocking indefinitely.
result< void > try_send_until(const T &item, const std::chrono::time_point< Clock, Duration > &deadline)
Sends an item to the back of the queue with a deadline.
T receive(const std::chrono::duration< Rep, Period > &timeout)
Receives an item from the queue with a timeout.
static result< queue > make(size_t length, flags< memory::capabilities > mem_caps=memory::capabilities::dram)
Creates a queue with the specified capacity.
result< T > try_receive_until(const std::chrono::time_point< Clock, Duration > &deadline)
Receives an item from the queue with a deadline.
void send(const T &item, const std::chrono::duration< Rep, Period > &timeout)
Sends an item to the back of the queue with a timeout.
void overwrite(const T &item) noexcept
Overwrites the last item in the queue, or sends if the queue is not full.
constexpr TickType_t ticks(const std::chrono::duration< Rep, Period > &d)
Converts a std::chrono duration to TickType_t ticks.
@ dram
Internal DRAM (8-bit accessible)
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
@ invalid_state
Invalid state.
@ timeout
Operation timed out.
@ invalid_arg
Invalid argument.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
constexpr auto to_underlying(flags< E > f) noexcept
Returns the underlying integral value of a flags object.
Result of an ISR receive operation.
std::optional< T > item
The received item, or std::nullopt if the queue was empty.
bool yield
true if a context switch should be requested.
Result of an ISR send operation.
bool success
true if the item was sent successfully.
bool yield
true if a context switch should be requested.