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

Generated by: LCOV version 1.14