/** * @file mutex.hpp * @author Gustice * @brief Mutex Wrapper * * @copyright Copyright (c) 2024 */ #pragma once #include #include namespace fos { /** * @brief Mutex * @details FreeRTOS implementation uses already priority inheritance * and are recursively callable */ class Mutex { private: QueueHandle_t _handle; public: /// @brief Tick type (redefinition for convenience) using Tick = TickType_t; /// @brief Definition for endless waittime static constexpr Tick MaxDelay = portMAX_DELAY; /// @brief Constructor Mutex() { _handle = xSemaphoreCreateMutex(); assert(_handle != 0 && "Semaphore create must finish successfully"); } ~Mutex() { vSemaphoreDelete(_handle); }; /// @brief Relase mutex void release() { auto ret = xSemaphoreGive(_handle); assert(ret == pdPASS && "Underlying semaphore queue must be initialized correcty"); } /// @brief Take mutex /// @param timeout Timeout to wait for signal (default = wait forever) /// @return true if successfully claimed (not timeout) bool claim(Tick timeout = MaxDelay) { auto ret = xSemaphoreTake(_handle, timeout); return ret == pdPASS; } }; /** * @brief Mutex Guard. Self releasing mutex for atomic operation */ class MutexGuard { private: Mutex &_mutex; bool _claimed; public: /// @brief Constructor /// @param mtx Mutex to claim /// @param timeout Timeout to wait for signal (default = wait forever) MutexGuard(Mutex &mtx, Mutex::Tick timeout = Mutex::MaxDelay) : _mutex(mtx) { _claimed = _mutex.claim(timeout); }; ~MutexGuard() { if (!_claimed) { return; } _mutex.release(); } /// @brief Check if mutex was claimed successfully /// @return true if claimed bool isActive() { return _claimed; } }; } // namespace fos