LCOV - code coverage report
Current view: top level - asyncFreeRtos/include/async - TaskInitializer.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 61 62 98.4 %
Date: 2025-10-07 10:52:16 Functions: 50 50 100.0 %

          Line data    Source code
       1             : // Copyright 2024 Accenture.
       2             : 
       3             : #pragma once
       4             : 
       5             : #include "async/StaticRunnable.h"
       6             : #include "async/Types.h"
       7             : 
       8             : #include <etl/array.h>
       9             : #include <etl/memory.h>
      10             : #include <etl/span.h>
      11             : #include <util/estd/assert.h>
      12             : 
      13             : #include <FreeRTOS.h>
      14             : #include <task.h>
      15             : #include <timers.h>
      16             : 
      17             : namespace async
      18             : {
      19             : namespace internal
      20             : {
      21             : 
      22           4 : constexpr size_t adjustStackSize(size_t const stackSize)
      23             : {
      24             : #if (defined(MINIMUM_STACK_SIZE)) && (MINIMUM_STACK_SIZE != 0)
      25           4 :     return (stackSize != 0U) && (stackSize < MINIMUM_STACK_SIZE) ? MINIMUM_STACK_SIZE : stackSize;
      26             : #else
      27             :     return stackSize;
      28             : #endif // (defined(MINIMUM_STACK_SIZE)) && (MINIMUM_STACK_SIZE != 0)
      29             : }
      30             : 
      31          38 : inline ::etl::span<uint8_t> align(size_t const alignment, ::etl::span<uint8_t> s)
      32             : {
      33          38 :     auto const mod = reinterpret_cast<size_t>(s.data()) % alignment;
      34          38 :     if (mod != 0)
      35             :     {
      36           0 :         return s.subspan(alignment - mod);
      37             :     }
      38             :     else
      39             :     {
      40          38 :         return s;
      41             :     }
      42             : }
      43             : 
      44             : template<size_t StackSize>
      45             : using Stack = ::etl::array<
      46             :     StackType_t,
      47             :     (adjustStackSize(StackSize) + sizeof(StackType_t) - 1) / sizeof(StackType_t)>;
      48             : 
      49             : /**
      50             :  * The TaskInitializer struct centralizes the initialization of tasks within the application.
      51             :  *
      52             :  * This struct provides a standardized way to set up tasks, defining key types and handling
      53             :  * configuration and setup of task and timer objects. It uses a specified Adapter type
      54             :  * for flexibility, allowing for different configurations.
      55             :  *
      56             :  * \tparam Adapter The adapter type used to provide specific task configuration types and functions.
      57             :  */
      58             : template<typename Adapter>
      59             : struct TaskInitializer : public StaticRunnable<TaskInitializer<Adapter>>
      60             : {
      61             :     using AdapterType      = Adapter;
      62             :     using StackSliceType   = ::etl::span<StackType_t>;
      63             :     using TaskConfigType   = typename AdapterType::TaskConfigType;
      64             :     using TaskFunctionType = typename AdapterType::TaskFunctionType;
      65             :     using TaskObjectType   = StaticTask_t;
      66             : 
      67             :     /**
      68             :      * Creates and initializes a task with the specified parameters.
      69             :      *
      70             :      * This function handles task creation by allocating memory for the object,
      71             :      * setting up the context, stack, and configuration,
      72             :      * and linking them to the specified task and timer objects.
      73             :      *
      74             :      * \tparam T The type of the stack used by the task.
      75             :      * \param context The execution context of the task.
      76             :      * \param name The name of the task.
      77             :      * \param task The static task object to initialize.
      78             :      * \param timer The static timer object associated with the task.
      79             :      * \param stack The stack to use for the task's execution.
      80             :      * \param taskFunction The function that the task will execute.
      81             :      * \param config Configuration settings for the task.
      82             :      */
      83             :     template<typename T>
      84             :     static void create(
      85             :         ContextType context,
      86             :         char const* name,
      87             :         TaskObjectType& task,
      88             :         T& stack,
      89             :         TaskFunctionType taskFunction,
      90             :         TaskConfigType const& config);
      91             : 
      92             : private:
      93             :     TaskInitializer(
      94             :         ContextType context,
      95             :         char const* name,
      96             :         TaskObjectType& task,
      97             :         StackSliceType const& stack,
      98             :         TaskFunctionType taskFunction,
      99             :         TaskConfigType const& config);
     100             : 
     101             : public:
     102             :     /// Executes task object initialization.
     103             :     void execute();
     104             : 
     105             :     /// The stack slice used for task execution.
     106             :     StackSliceType _stack;
     107             : 
     108             :     /// The function assigned for the task's execution.
     109             :     TaskFunctionType _taskFunction;
     110             : 
     111             :     /// Reference to the static task object.
     112             :     TaskObjectType& _task;
     113             :     /// The name of the task.
     114             :     char const* _name;
     115             : 
     116             :     /// The context in which the task will execute.
     117             :     ContextType _context;
     118             : 
     119             :     /// The configuration settings for the task.
     120             :     TaskConfigType _config;
     121             : };
     122             : 
     123             : /**
     124             :  * Primary template class that serves as a container for task-related objects and
     125             :  * configuration.
     126             :  *
     127             :  * TaskImpl provides a structure to hold essential components for tasks, such as the stack, task
     128             :  * object, and timer object, along with configuration settings. It serves as a base for derived task
     129             :  * classes (e.g., Task, IdleTask) and is designed for integration with FreeRTOS, using the Adapter
     130             :  * type for flexibility.
     131             :  *
     132             :  * \tparam Adapter The adapter type that supplies specific task configuration types and functions.
     133             :  * \tparam Context The context in which the task operates.
     134             :  * \tparam StackSize The size of the stack allocated for the task.
     135             :  */
     136             : template<class Adapter, ContextType Context, size_t StackSize = 0U>
     137             : class TaskImpl
     138             : {
     139             : public:
     140             :     using AdapterType      = Adapter;
     141             :     using StackSliceType   = ::etl::span<StackType_t>;
     142             :     using TaskConfigType   = typename AdapterType::TaskConfigType;
     143             :     using TaskFunctionType = typename AdapterType::TaskFunctionType;
     144             :     using TaskObjectType   = StaticTask_t;
     145             : 
     146             :     TaskImpl(char const* name, TaskFunctionType taskFunction, TaskConfigType const& taskConfig);
     147             : 
     148             : protected:
     149             :     ~TaskImpl() = default;
     150             : 
     151             : private:
     152             :     Stack<StackSize> _stack;
     153             :     TaskObjectType _task;
     154             : };
     155             : 
     156             : template<class Adapter, ContextType Context>
     157             : class TaskImpl<Adapter, Context, 0U>
     158             : {
     159             : public:
     160             :     using AdapterType      = Adapter;
     161             :     using StackSliceType   = ::etl::span<StackType_t>;
     162             :     using TaskConfigType   = typename AdapterType::TaskConfigType;
     163             :     using TaskFunctionType = typename AdapterType::TaskFunctionType;
     164             :     using TaskObjectType   = StaticTask_t;
     165             : 
     166             :     template<typename T>
     167             :     TaskImpl(
     168             :         char const* name,
     169             :         T& stack,
     170             :         TaskFunctionType taskFunction,
     171             :         TaskConfigType const& taskConfig);
     172             : 
     173             : protected:
     174             :     ~TaskImpl() = default;
     175             : 
     176             : private:
     177             :     TaskObjectType _task;
     178             : };
     179             : 
     180             : template<class Adapter, size_t StackSize = 0U>
     181             : struct IdleTask : public TaskImpl<Adapter, Adapter::TASK_IDLE, StackSize>
     182             : {
     183             :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     184             :     using TaskConfigType   = typename Adapter::TaskConfigType;
     185             : 
     186             :     IdleTask(char const* name, TaskConfigType const& taskConfig = TaskConfigType());
     187             : 
     188             :     IdleTask(
     189             :         char const* name,
     190             :         TaskFunctionType taskFunction,
     191             :         TaskConfigType const& taskConfig = TaskConfigType());
     192             : };
     193             : 
     194             : template<class Adapter>
     195             : struct IdleTask<Adapter, 0U> : public TaskImpl<Adapter, Adapter::TASK_IDLE>
     196             : {
     197             :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     198             :     using TaskConfigType   = typename Adapter::TaskConfigType;
     199             : 
     200             :     template<typename T>
     201             :     IdleTask(char const* name, T& stack, TaskConfigType const& taskConfig = TaskConfigType());
     202             : 
     203             :     template<typename T>
     204             :     IdleTask(
     205             :         char const* name,
     206             :         T& stack,
     207             :         TaskFunctionType taskFunction,
     208             :         TaskConfigType const& taskConfig = TaskConfigType());
     209             : };
     210             : 
     211             : template<class Adapter, size_t StackSize = 0U>
     212             : struct TimerTask : public TaskImpl<Adapter, Adapter::TASK_TIMER, StackSize>
     213             : {
     214             :     using TaskConfigType = typename Adapter::TaskConfigType;
     215             : 
     216             :     explicit TimerTask(char const* name, TaskConfigType const& taskConfig = TaskConfigType());
     217             : };
     218             : 
     219             : template<class Adapter>
     220             : struct TimerTask<Adapter, 0U> : public TaskImpl<Adapter, Adapter::TASK_TIMER>
     221             : {
     222             :     using TaskConfigType = typename Adapter::TaskConfigType;
     223             : 
     224             :     template<typename T>
     225             :     TimerTask(char const* name, T& stack, TaskConfigType const& taskConfig = TaskConfigType());
     226             : };
     227             : 
     228             : template<class Adapter, ContextType Context, size_t StackSize = 0U>
     229             : struct Task : public TaskImpl<Adapter, Context, StackSize>
     230             : {
     231             :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     232             :     using TaskConfigType   = typename Adapter::TaskConfigType;
     233             : 
     234             :     explicit Task(char const* name, TaskConfigType const& taskConfig = TaskConfigType());
     235             : 
     236             :     Task(
     237             :         char const* name,
     238             :         TaskFunctionType taskFunction,
     239             :         TaskConfigType const& taskConfig = TaskConfigType());
     240             : };
     241             : 
     242             : template<class Adapter, ContextType Context>
     243             : struct Task<Adapter, Context, 0U> : public TaskImpl<Adapter, Context>
     244             : {
     245             :     using TaskFunctionType = typename Adapter::TaskFunctionType;
     246             :     using TaskConfigType   = typename Adapter::TaskConfigType;
     247             : 
     248             :     template<typename T>
     249             :     explicit Task(char const* name, T& stack, TaskConfigType const& taskConfig = TaskConfigType());
     250             : 
     251             :     template<typename T>
     252             :     Task(
     253             :         char const* name,
     254             :         T& stack,
     255             :         TaskFunctionType taskFunction,
     256             :         TaskConfigType const& taskConfig = TaskConfigType());
     257             : };
     258             : 
     259             : template<class Adapter>
     260             : template<typename T>
     261          19 : void TaskInitializer<Adapter>::create(
     262             :     ContextType const context,
     263             :     char const* const name,
     264             :     TaskObjectType& task,
     265             :     T& stack,
     266             :     TaskFunctionType const taskFunction,
     267             :     TaskConfigType const& config)
     268             : {
     269          19 :     auto const stackSliceRaw = ::etl::make_span(stack).template reinterpret_as<uint8_t>();
     270          19 :     auto const stackSlice
     271          19 :         = align(alignof(StackType_t), stackSliceRaw).template reinterpret_as<StackType_t>();
     272          19 :     auto const taskInitializerSlice = align(alignof(TaskInitializer), stackSliceRaw);
     273          19 :     estd_assert((taskInitializerSlice.size()) >= sizeof(TaskInitializer));
     274          18 :     new (taskInitializerSlice.data())
     275             :         TaskInitializer(context, name, task, stackSlice, taskFunction, config);
     276          18 : }
     277             : 
     278             : template<class Adapter>
     279          18 : TaskInitializer<Adapter>::TaskInitializer(
     280             :     ContextType const context,
     281             :     char const* const name,
     282             :     TaskObjectType& task,
     283             :     StackSliceType const& stack,
     284             :     TaskFunctionType const taskFunction,
     285             :     TaskConfigType const& config)
     286          18 : : _stack(stack)
     287          18 : , _taskFunction(taskFunction)
     288          18 : , _task(task)
     289          18 : , _name(name)
     290          18 : , _context(context)
     291          18 : , _config(config)
     292          18 : {}
     293             : 
     294             : template<class Adapter>
     295          18 : void TaskInitializer<Adapter>::execute()
     296             : {
     297          18 :     Adapter::initTask(*this);
     298          18 : }
     299             : 
     300             : template<class Adapter, ContextType Context, size_t StackSize>
     301          14 : TaskImpl<Adapter, Context, StackSize>::TaskImpl(
     302             :     char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig)
     303             : {
     304          14 :     TaskInitializer<Adapter>::create(Context, name, _task, _stack, taskFunction, taskConfig);
     305          13 : }
     306             : 
     307             : template<class Adapter, ContextType Context>
     308             : template<typename T>
     309           5 : TaskImpl<Adapter, Context, 0U>::TaskImpl(
     310             :     char const* const name,
     311             :     T& stack,
     312             :     TaskFunctionType const taskFunction,
     313             :     TaskConfigType const& taskConfig)
     314             : {
     315           5 :     TaskInitializer<Adapter>::create(Context, name, _task, stack, taskFunction, taskConfig);
     316           5 : }
     317             : 
     318             : template<class Adapter, size_t StackSize>
     319           1 : IdleTask<Adapter, StackSize>::IdleTask(char const* const name, TaskConfigType const& taskConfig)
     320           1 : : TaskImpl<Adapter, Adapter::TASK_IDLE, StackSize>(name, TaskFunctionType(), taskConfig)
     321           1 : {}
     322             : 
     323             : template<class Adapter, size_t StackSize>
     324           2 : IdleTask<Adapter, StackSize>::IdleTask(
     325             :     char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig)
     326           2 : : TaskImpl<Adapter, Adapter::TASK_IDLE, StackSize>(name, taskFunction, taskConfig)
     327           2 : {}
     328             : 
     329             : template<class Adapter>
     330             : template<typename T>
     331           1 : IdleTask<Adapter, 0U>::IdleTask(char const* const name, T& stack, TaskConfigType const& taskConfig)
     332           1 : : TaskImpl<Adapter, Adapter::TASK_IDLE>(name, stack, TaskFunctionType(), taskConfig)
     333           1 : {}
     334             : 
     335             : template<class Adapter>
     336             : template<typename T>
     337           1 : IdleTask<Adapter, 0U>::IdleTask(
     338             :     char const* const name,
     339             :     T& stack,
     340             :     TaskFunctionType const taskFunction,
     341             :     TaskConfigType const& taskConfig)
     342           1 : : TaskImpl<Adapter, Adapter::TASK_IDLE>(name, stack, taskFunction, taskConfig)
     343           1 : {}
     344             : 
     345             : template<class Adapter, size_t StackSize>
     346           2 : TimerTask<Adapter, StackSize>::TimerTask(char const* const name, TaskConfigType const& taskConfig)
     347             : : TaskImpl<Adapter, Adapter::TASK_TIMER, StackSize>(
     348           2 :     name, typename Adapter::TaskFunctionType(), taskConfig)
     349           2 : {}
     350             : 
     351             : template<class Adapter>
     352             : template<typename T>
     353           1 : TimerTask<Adapter, 0U>::TimerTask(
     354             :     char const* const name, T& stack, TaskConfigType const& taskConfig)
     355             : : TaskImpl<Adapter, Adapter::TASK_TIMER>(
     356           1 :     name, stack, typename Adapter::TaskFunctionType(), taskConfig)
     357           1 : {}
     358             : 
     359             : template<class Adapter, ContextType Context, size_t StackSize>
     360           5 : Task<Adapter, Context, StackSize>::Task(char const* const name, TaskConfigType const& taskConfig)
     361           5 : : TaskImpl<Adapter, Context, StackSize>(name, TaskFunctionType(), taskConfig)
     362           4 : {}
     363             : 
     364             : template<class Adapter, ContextType Context, size_t StackSize>
     365           4 : Task<Adapter, Context, StackSize>::Task(
     366             :     char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig)
     367           4 : : TaskImpl<Adapter, Context, StackSize>(name, taskFunction, taskConfig)
     368           4 : {}
     369             : 
     370             : template<class Adapter, ContextType Context>
     371             : template<typename T>
     372           1 : Task<Adapter, Context, 0U>::Task(char const* const name, T& stack, TaskConfigType const& taskConfig)
     373           1 : : TaskImpl<Adapter, Context>(name, stack, typename Adapter::TaskFunctionType(), taskConfig)
     374           1 : {}
     375             : 
     376             : template<class Adapter, ContextType Context>
     377             : template<typename T>
     378           1 : Task<Adapter, Context, 0U>::Task(
     379             :     char const* const name,
     380             :     T& stack,
     381             :     TaskFunctionType const taskFunction,
     382             :     TaskConfigType const& taskConfig)
     383           1 : : TaskImpl<Adapter, Context>(name, stack, taskFunction, taskConfig)
     384           1 : {}
     385             : 
     386             : } // namespace internal
     387             : } // namespace async

Generated by: LCOV version 1.14