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), std::to_underlying(mem_type));
85 if (_handle ==
nullptr) {
105 auto q = std::unique_ptr<queue>(
new queue());
106 q->_handle = xQueueCreateWithCaps(length,
sizeof(T), std::to_underlying(mem_type));
107 if (q->_handle ==
nullptr) {
119 if (_handle !=
nullptr) {
120 vQueueDeleteWithCaps(_handle);
134#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
159 template<
typename Rep,
typename Period>
160 void send(
const T& item,
const std::chrono::duration<Rep, Period>&
timeout) {
177 template<
typename Clock,
typename Duration>
178 void send_until(
const T& item,
const std::chrono::time_point<Clock, Duration>& deadline) {
208 template<
typename Rep,
typename Period>
227 template<
typename Clock,
typename Duration>
256 template<
typename Rep,
typename Period>
273 template<
typename Clock,
typename Duration>
275 auto remaining = deadline - Clock::now();
276 if (remaining <=
decltype(remaining)::zero()) {
277 return _try_send(item, 0);
307 template<
typename Rep,
typename Period>
325 template<
typename Clock,
typename Duration>
328 auto remaining = deadline - Clock::now();
329 if (remaining <=
decltype(remaining)::zero()) {
330 return _try_send_to_front(item, 0);
339#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
366 void try_overwrite(
const T& item)
noexcept { xQueueOverwrite(_handle, &item); }
372#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
397 template<
typename Rep,
typename Period>
415 template<
typename Clock,
typename Duration>
416 [[nodiscard]] T
receive_until(
const std::chrono::time_point<Clock, Duration>& deadline) {
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 BaseType_t woken = pdFALSE;
611 BaseType_t ret = xQueueSendFromISR(_handle, &item, &woken);
612 return {ret == pdTRUE, woken == pdTRUE};
633 BaseType_t woken = pdFALSE;
634 BaseType_t ret = xQueueSendToFrontFromISR(_handle, &item, &woken);
635 return {ret == pdTRUE, woken == pdTRUE};
658 BaseType_t woken = pdFALSE;
659 xQueueOverwriteFromISR(_handle, &item, &woken);
660 return woken == pdTRUE;
684 BaseType_t woken = pdFALSE;
685 if (xQueueReceiveFromISR(_handle, &item, &woken) == pdTRUE) {
686 return {item, woken == pdTRUE};
688 return {std::nullopt, woken == pdTRUE};
706 if (xQueuePeekFromISR(_handle, &item) == pdTRUE) {
721 [[nodiscard]]
size_t size() const noexcept {
return uxQueueMessagesWaiting(_handle); }
728 [[nodiscard]]
size_t available() const noexcept {
return uxQueueSpacesAvailable(_handle); }
735 [[nodiscard]]
bool empty() const noexcept {
return uxQueueMessagesWaiting(_handle) == 0; }
742 [[nodiscard]]
bool full() const noexcept {
return uxQueueSpacesAvailable(_handle) == 0; }
752 [[nodiscard]] QueueHandle_t
idf_handle() const noexcept {
return _handle; }
759 void reset() noexcept { xQueueReset(_handle); }
763 : _handle(
nullptr) {}
765 [[nodiscard]] result<void> _try_send(
const T& item, TickType_t ticks) {
766 if (xQueueSend(_handle, &item, ticks) != pdTRUE) {
772 [[nodiscard]] result<void> _try_send_to_front(
const T& item, TickType_t ticks) {
773 if (xQueueSendToFront(_handle, &item, ticks) != pdTRUE) {
779 [[nodiscard]] result<T> _try_receive(TickType_t ticks) {
781 if (xQueueReceive(_handle, &item, ticks) != pdTRUE) {
787 [[nodiscard]] result<T> _try_peek(TickType_t ticks) {
789 if (xQueuePeek(_handle, &item, ticks) != pdTRUE) {
795 QueueHandle_t _handle;
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 try_overwrite(const T &item) noexcept
Overwrites the last item in the queue, or sends if the queue is not full.
static result< std::unique_ptr< queue > > make(size_t length, memory_type mem_type=memory_type::internal)
Creates a queue with the specified capacity.
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.
queue(size_t length, memory_type mem_type=memory_type::internal)
Creates a queue with the specified capacity.
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.
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.
queue & operator=(queue &&)=delete
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.
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.
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.
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.
memory_type
Memory region type for heap allocations.
@ internal
Internal DRAM (default)
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.
@ timeout
Operation timed out.
@ invalid_arg
Invalid argument.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
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.