184 lines
5.2 KiB
C++
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
|