Files
lab-rv32i-freertos-semaphor…/include/freertos/synchronization.hpp
T

184 lines
5.2 KiB
C++

#ifndef FREERTOS_CPP_SYNCHRONIZATION_HPP
#define FREERTOS_CPP_SYNCHRONIZATION_HPP
#include <stdint.h>
#include <type_traits>
extern "C"
{
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
}
namespace freertos
{
struct StaticSemaphoreStorage final
{
StaticSemaphore_t control {};
};
class BinarySemaphore final
{
public:
explicit BinarySemaphore( StaticSemaphoreStorage & storage ) noexcept
: handle_ { xSemaphoreCreateBinaryStatic( &storage.control ) }
{
}
~BinarySemaphore() noexcept
{
if( handle_ != nullptr ) vSemaphoreDelete( handle_ );
}
BinarySemaphore( const BinarySemaphore & ) = delete;
BinarySemaphore & operator=( const BinarySemaphore & ) = delete;
BinarySemaphore( BinarySemaphore && ) = delete;
BinarySemaphore & operator=( BinarySemaphore && ) = delete;
[[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; }
[[nodiscard]] bool give() noexcept
{
return handle_ != nullptr && xSemaphoreGive( handle_ ) == pdPASS;
}
[[nodiscard]] bool take( TickType_t timeout ) noexcept
{
return handle_ != nullptr &&
xSemaphoreTake( handle_, timeout ) == pdPASS;
}
[[nodiscard]] UBaseType_t count() const noexcept
{
return handle_ == nullptr ? 0U : uxSemaphoreGetCount( handle_ );
}
[[nodiscard]] SemaphoreHandle_t native_handle() const noexcept
{
return handle_;
}
private:
SemaphoreHandle_t handle_ {};
};
template< UBaseType_t Maximum >
class CountingSemaphore final
{
static_assert( Maximum > 0U, "CountingSemaphore maximum must be positive" );
public:
CountingSemaphore( StaticSemaphoreStorage & storage,
UBaseType_t initial ) noexcept
: handle_ { initial <= Maximum ?
xSemaphoreCreateCountingStatic(
Maximum, initial, &storage.control ) : nullptr }
{
}
~CountingSemaphore() noexcept
{
if( handle_ != nullptr ) vSemaphoreDelete( handle_ );
}
CountingSemaphore( const CountingSemaphore & ) = delete;
CountingSemaphore & operator=( const CountingSemaphore & ) = delete;
CountingSemaphore( CountingSemaphore && ) = delete;
CountingSemaphore & operator=( CountingSemaphore && ) = delete;
[[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; }
[[nodiscard]] bool give() noexcept
{
return handle_ != nullptr && xSemaphoreGive( handle_ ) == pdPASS;
}
[[nodiscard]] bool take( TickType_t timeout ) noexcept
{
return handle_ != nullptr &&
xSemaphoreTake( handle_, timeout ) == pdPASS;
}
[[nodiscard]] UBaseType_t count() const noexcept
{
return handle_ == nullptr ? 0U : uxSemaphoreGetCount( handle_ );
}
static constexpr UBaseType_t maximum() noexcept { return Maximum; }
[[nodiscard]] SemaphoreHandle_t native_handle() const noexcept
{
return handle_;
}
private:
SemaphoreHandle_t handle_ {};
};
enum class NotificationAction : uint8_t
{
no_action,
set_bits,
increment,
overwrite,
without_overwrite
};
class TaskNotification final
{
public:
explicit constexpr TaskNotification( TaskHandle_t target ) noexcept
: target_ { target }
{
}
[[nodiscard]] bool valid() const noexcept { return target_ != nullptr; }
[[nodiscard]] bool give() const noexcept
{
return target_ != nullptr && xTaskNotifyGive( target_ ) == pdPASS;
}
[[nodiscard]] bool notify( uint32_t value,
NotificationAction action ) const noexcept
{
return target_ != nullptr &&
xTaskNotify( target_, value, raw_action( action ) ) == pdPASS;
}
[[nodiscard]] static uint32_t take( bool clear_on_exit,
TickType_t timeout ) noexcept
{
return ulTaskNotifyTake( clear_on_exit ? pdTRUE : pdFALSE, timeout );
}
[[nodiscard]] static bool wait_value( uint32_t & value,
TickType_t timeout,
uint32_t clear_on_entry = 0U,
uint32_t clear_on_exit = UINT32_MAX ) noexcept
{
return xTaskNotifyWait( clear_on_entry, clear_on_exit,
&value, timeout ) == pdPASS;
}
[[nodiscard]] TaskHandle_t target() const noexcept { return target_; }
private:
static eNotifyAction raw_action( NotificationAction action ) noexcept
{
switch( action )
{
case NotificationAction::no_action: return eNoAction;
case NotificationAction::set_bits: return eSetBits;
case NotificationAction::increment: return eIncrement;
case NotificationAction::overwrite: return eSetValueWithOverwrite;
case NotificationAction::without_overwrite:
return eSetValueWithoutOverwrite;
}
return eNoAction;
}
TaskHandle_t target_ {};
};
static_assert( !std::is_copy_constructible< BinarySemaphore >::value );
static_assert( !std::is_move_constructible< CountingSemaphore< 2U > >::value );
static_assert( std::is_trivially_copyable< TaskNotification >::value );
} // namespace freertos
#endif