/** * @file queue.hpp * @author Gustice * @brief Queue Wrapper * * @copyright Copyright (c) 2024 */ #pragma once #include #include #include #include namespace fos { /** * @brief Message Queue * * @tparam T Type for message payload */ template class Queue { private: bool _isActive; QueueHandle_t xQueue; public: /// @brief Tick type (redefinition for convenience) using Tick = TickType_t; /// @brief Definition for endless waittime static constexpr Tick MaxDelay = portMAX_DELAY; /// @brief Constructor /// @param size number of slots in queue Queue(size_t size) { xQueue = xQueueCreate(size, sizeof(T *)); assert(xQueue != 0 && "Queue create must finish successfully"); _isActive = true; } ~Queue() { vQueueDelete(xQueue); } /// @brief Push new message in queue /// @param message payload /// @return nullptr if successful else give back pointer to queued element if pushing failed std::unique_ptr enqueue(std::unique_ptr message) { if (uxQueueSpacesAvailable(xQueue) == 0) { return message; } T *o = message.release(); auto ret = xQueueSend(xQueue, &o, (TickType_t)0); assert(ret == pdPASS && "Underlying semaphore queue must be initialized correcty"); return message; } /// @brief Pop message from queue /// @param timeout timeout to wait for message (default: wait for ever) /// @return pointer to dequeued element std::unique_ptr dequeue(Tick timeout = MaxDelay) { T *pMsg = nullptr; if (!xQueueReceive(xQueue, &pMsg, timeout)) { return {nullptr}; } return std::unique_ptr(pMsg); } /// @brief Pop latest element from queue and ignore all older elements /// @param timeout timeout to wait for message (default: wait for ever) /// @return pointer to dequeued element std::unique_ptr dequeueLatest(Tick timeout = MaxDelay) { T *pMsg = nullptr; if (!xQueueReceive(xQueue, &pMsg, timeout)) { return {nullptr}; } while (true == xQueueReceive(xQueue, &pMsg, (TickType_t)0)) { } return std::unique_ptr(pMsg); } /// @brief terminate message queue void signalClose() { _isActive = false; } /// @brief Check if message queue is active /// @return true if active bool isActive() { return _isActive; } }; } // namespace fos