Files
lab-rv32i-freertos-mutex/include/freertos/mutex.hpp
T
2026-07-21 19:14:19 +02:00

107 lines
2.3 KiB
C++

#ifndef FREERTOS_CPP_MUTEX_HPP
#define FREERTOS_CPP_MUTEX_HPP
#include <type_traits>
extern "C"
{
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
}
namespace freertos
{
struct StaticMutexStorage final
{
StaticSemaphore_t control {};
};
class Mutex final
{
public:
explicit Mutex( StaticMutexStorage & storage ) noexcept
: handle_ { xSemaphoreCreateMutexStatic( &storage.control ) }
{
}
~Mutex() noexcept
{
if( handle_ != nullptr )
{
vSemaphoreDelete( handle_ );
}
}
Mutex( const Mutex & ) = delete;
Mutex & operator=( const Mutex & ) = delete;
Mutex( Mutex && ) = delete;
Mutex & operator=( Mutex && ) = delete;
[[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; }
[[nodiscard]] bool lock( TickType_t timeout ) noexcept
{
return handle_ != nullptr &&
xSemaphoreTake( handle_, timeout ) == pdPASS;
}
[[nodiscard]] bool unlock() noexcept
{
return handle_ != nullptr && xSemaphoreGive( handle_ ) == pdPASS;
}
[[nodiscard]] TaskHandle_t owner() const noexcept
{
return handle_ == nullptr ? nullptr :
xSemaphoreGetMutexHolder( handle_ );
}
[[nodiscard]] SemaphoreHandle_t native_handle() const noexcept
{
return handle_;
}
private:
SemaphoreHandle_t handle_ {};
};
template< typename Lockable >
class LockGuard final
{
public:
explicit LockGuard( Lockable & lockable, TickType_t timeout ) noexcept
: lockable_ { &lockable }, owns_ { lockable.lock( timeout ) }
{
}
~LockGuard() noexcept
{
if( owns_ )
{
( void ) lockable_->unlock();
}
}
LockGuard( const LockGuard & ) = delete;
LockGuard & operator=( const LockGuard & ) = delete;
LockGuard( LockGuard && ) = delete;
LockGuard & operator=( LockGuard && ) = delete;
[[nodiscard]] bool owns_lock() const noexcept { return owns_; }
private:
Lockable * const lockable_;
const bool owns_;
};
static_assert( !std::is_copy_constructible< Mutex >::value );
static_assert( !std::is_move_constructible< Mutex >::value );
static_assert( !std::is_copy_constructible< LockGuard< Mutex > >::value );
static_assert( !std::is_move_constructible< LockGuard< Mutex > >::value );
} // namespace freertos
#endif