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-01-20 13:53:09 Functions: 22 22 100.0 %

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

Generated by: LCOV version 1.14