#ifndef FREERTOS_CPP_EXPLICIT_TASK_HPP #define FREERTOS_CPP_EXPLICIT_TASK_HPP #include #include extern "C" { #include "FreeRTOS.h" #include "task.h" } #ifndef FREERTOS_TASK_CHECKPOINT #define FREERTOS_TASK_CHECKPOINT( point, object ) \ do \ { \ ( void ) ( point ); \ ( void ) ( object ); \ } while( 0 ) #endif namespace freertos { enum class TaskState : uint8_t { constructed, starting, ready, running, completed, start_failed }; template< typename Derived > class Task { public: constexpr Task( const char * name, configSTACK_DEPTH_TYPE stack_words, UBaseType_t priority ) noexcept : name_ { name }, stack_words_ { stack_words }, priority_ { priority } { } Task( const Task & ) = delete; Task & operator=( const Task & ) = delete; Task( Task && ) = delete; Task & operator=( Task && ) = delete; bool start() noexcept { static_assert( std::is_base_of< Task< Derived >, Derived >::value, "Derived must inherit Task" ); if( state_ != TaskState::constructed ) { return false; } state_ = TaskState::starting; FREERTOS_TASK_CHECKPOINT( 2U, this ); /* * Mark ready before entering the kernel: with a live scheduler a * higher-priority new task may complete before xTaskCreate returns. */ state_ = TaskState::ready; FREERTOS_TASK_CHECKPOINT( 3U, this ); const BaseType_t created = xTaskCreate( &Task::trampoline, name_, stack_words_, static_cast< Derived * >( this ), priority_, &handle_ ); if( created != pdPASS ) { handle_ = nullptr; state_ = TaskState::start_failed; return false; } FREERTOS_TASK_CHECKPOINT( 4U, this ); return true; } TaskHandle_t native_handle() const noexcept { return handle_; } TaskState state() const noexcept { return state_; } const char * name() const noexcept { return name_; } private: static void trampoline( void * context ) { Derived * const derived = static_cast< Derived * >( context ); Task & base = *static_cast< Task * >( derived ); FREERTOS_TASK_CHECKPOINT( 6U, derived ); base.state_ = TaskState::running; FREERTOS_TASK_CHECKPOINT( 7U, derived ); derived->run(); base.state_ = TaskState::completed; base.handle_ = nullptr; FREERTOS_TASK_CHECKPOINT( 10U, derived ); vTaskDelete( nullptr ); for( ;; ) { } } TaskHandle_t handle_ {}; const char * const name_; const configSTACK_DEPTH_TYPE stack_words_; const UBaseType_t priority_; volatile TaskState state_ { TaskState::constructed }; }; } // namespace freertos #endif