LCOV - code coverage report
Current view: top level - asyncFreeRtos/include/async - FreeRtosAdapter.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 96 96 100.0 %
Date: 2025-01-20 13:53:09 Functions: 16 16 100.0 %

          Line data    Source code
       1             : // Copyright 2024 Accenture.
       2             : 
       3             : /**
       4             :  * \ingroup async
       5             :  */
       6             : #ifndef GUARD_DB9C7111_F66E_4D50_B724_5DF992A19ED0
       7             : #define GUARD_DB9C7111_F66E_4D50_B724_5DF992A19ED0
       8             : 
       9             : #include "async/TaskContext.h"
      10             : #include "async/TaskInitializer.h"
      11             : 
      12             : #ifndef ASYNC_LOOPER_DISABLE
      13             : #include <looper/looper.h>
      14             : #endif // ASYNC_LOOPER_DISABLE
      15             : 
      16             : #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE
      17             : #include <util/timeout/AsyncTimeoutManager.h>
      18             : #endif // ASYNC_TIMEOUTMANAGER2_DISABLE
      19             : 
      20             : #include <estd/array.h>
      21             : #include <estd/singleton.h>
      22             : 
      23             : namespace async
      24             : {
      25             : namespace internal
      26             : {
      27             : template<bool HasNestedInterrupts = (ASYNC_CONFIG_NESTED_INTERRUPTS != 0)>
      28          10 : class NestedInterruptLock : public LockType
      29             : {};
      30             : 
      31             : template<>
      32             : class NestedInterruptLock<false>
      33             : {};
      34             : 
      35             : template<size_t N, typename TaskConfig = ASYNC_TASK_CONFIG_TYPE>
      36             : class TaskConfigHolder
      37             : {
      38             : public:
      39             :     using TaskConfigType = TaskConfig;
      40             : 
      41             :     static void setTaskConfig(size_t taskIdx, TaskConfigType const& taskConfig);
      42             : 
      43             :     static TaskConfigType const* getTaskConfig(size_t taskIdx);
      44             : 
      45             : private:
      46             :     static ::estd::array<TaskConfigType, N> _taskConfigs;
      47             : };
      48             : 
      49             : template<size_t N>
      50             : class TaskConfigHolder<N, void>
      51             : {
      52             : public:
      53             :     struct TaskConfigType
      54             :     {};
      55             : 
      56             :     static void setTaskConfig(size_t taskIdx, TaskConfigType const& taskConfig);
      57             : 
      58             :     static TaskConfigType const* getTaskConfig(size_t taskIdx);
      59             : };
      60             : 
      61             : } // namespace internal
      62             : 
      63             : /**
      64             :  * Adapter class bridging FreeRTOS functionalities with the application's binding.
      65             :  *
      66             :  * The `FreeRtosAdapter` class serves as a centralized interface for managing tasks, timers,
      67             :  * and scheduling functionalities within a FreeRTOS environment. It utilizes the specified
      68             :  * `Binding` type to adapt and configure task-related components, such as `TaskContext`,
      69             :  * `TaskConfig`, and idle and timer tasks.
      70             :  *
      71             :  * \tparam Binding The binding type specifying application-specific configurations.
      72             :  */
      73             : template<class Binding>
      74             : class FreeRtosAdapter
      75             : {
      76             : public:
      77             :     static size_t const TASK_COUNT          = Binding::TASK_COUNT;
      78             :     static size_t const FREERTOS_TASK_COUNT = TASK_COUNT + 1U;
      79             :     static TickType_t const WAIT_EVENTS_TICK_COUNT
      80             :         = static_cast<TickType_t>(Binding::WAIT_EVENTS_TICK_COUNT);
      81             :     static ContextType const TASK_IDLE  = 0U;
      82             :     static ContextType const TASK_TIMER = static_cast<ContextType>(TASK_COUNT);
      83             : 
      84             :     using AdapterType = FreeRtosAdapter<Binding>;
      85             : 
      86             :     using TaskContextType  = TaskContext<AdapterType>;
      87             :     using TaskFunctionType = typename TaskContextType::TaskFunctionType;
      88             : 
      89             :     using TaskConfigsType = internal::TaskConfigHolder<FREERTOS_TASK_COUNT>;
      90             :     using TaskConfigType  = typename TaskConfigsType::TaskConfigType;
      91             : 
      92             :     template<size_t StackSize>
      93             :     using Stack           = internal::Stack<StackSize>;
      94             :     using TaskInitializer = internal::TaskInitializer<AdapterType>;
      95             : 
      96             :     template<size_t StackSize = 0U>
      97             :     using IdleTask = internal::IdleTask<AdapterType, StackSize>;
      98             :     template<size_t StackSize = 0U>
      99             :     using TimerTask = internal::TimerTask<AdapterType, StackSize>;
     100             :     template<ContextType Context, size_t StackSize = 0U>
     101             :     using Task = internal::Task<AdapterType, Context, StackSize>;
     102             : 
     103             :     /// Struct representing the stack usage for a specific task.
     104             :     struct StackUsage
     105             :     {
     106             :         StackUsage();
     107             : 
     108             :         uint32_t _stackSize;
     109             :         uint32_t _usedSize;
     110             :     };
     111             : 
     112             :     /**
     113             :      * Retrieves memory pointers for a FreeRTOS task.
     114             :      *
     115             :      * \tparam Context The task context.
     116             :      * \param ppxTaskTCBBuffer Pointer to the task control block buffer.
     117             :      * \param ppxTaskStackBuffer Pointer to the task stack buffer.
     118             :      * \param pulTaskStackSize Pointer to the task stack size.
     119             :      */
     120             :     template<ContextType Context>
     121             :     static void getTaskMemory(
     122             :         StaticTask_t** ppxTaskTCBBuffer,
     123             :         StackType_t** ppxTaskStackBuffer,
     124             :         uint32_t* pulTaskStackSize);
     125             : 
     126             :     static char const* getTaskName(size_t taskIdx);
     127             : 
     128             :     static TaskHandle_t getTaskHandle(size_t taskIdx);
     129             : 
     130             :     static TaskConfigType const* getTaskConfig(size_t taskIdx);
     131             : 
     132             :     static ContextType getCurrentTaskContext();
     133             : 
     134             : #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE
     135             :     /**
     136             :      * Retrieves the timeout manager for a given context.
     137             :      *
     138             :      * \param context The task context.
     139             :      * \return A reference to the timeout manager.
     140             :      */
     141             :     static ::common::ITimeoutManager2& getTimeoutManager(ContextType context);
     142             : #endif // ASYNC_TIMEOUTMANAGER2_DISABLE
     143             : 
     144             : #ifndef ASYNC_LOOPER_DISABLE
     145             :     /**
     146             :      * Retrieves the looper for a given context.
     147             :      *
     148             :      * \param context The task context.
     149             :      * \return A reference to the looper.
     150             :      */
     151             :     static ::loop::looper& getLooper(ContextType context);
     152             : #endif // ASYNC_LOOPER_DISABLE
     153             : 
     154             :     /// Initializes the FreeRTOS adapter and associated tasks.
     155             :     static void init();
     156             : 
     157             :     /// Starts the FreeRTOS scheduler.
     158             :     static void run();
     159             : 
     160             :     static void runningHook();
     161             : 
     162             :     /**
     163             :      * Retrieves the stack usage for a specified task.
     164             :      *
     165             :      * \param taskIdx The index of the task.
     166             :      * \param stackUsage A reference to the StackUsage struct to populate.
     167             :      * \return True if stack usage information is successfully retrieved.
     168             :      */
     169             :     static bool getStackUsage(size_t taskIdx, StackUsage& stackUsage);
     170             : 
     171             :     static void callIdleTaskFunction();
     172             : 
     173             :     /**
     174             :      * Executes a specified runnable within a given context.
     175             :      *
     176             :      * \param context The task context.
     177             :      * \param runnable The runnable to execute.
     178             :      */
     179             :     static void execute(ContextType context, RunnableType& runnable);
     180             : 
     181             :     /**
     182             :      * Schedules a runnable to execute after a delay.
     183             :      *
     184             :      * \param context The task context.
     185             :      * \param runnable The runnable to schedule.
     186             :      * \param timeout The timeout associated with the runnable.
     187             :      * \param delay The delay before execution.
     188             :      * \param unit The time unit for the delay.
     189             :      */
     190             :     static void schedule(
     191             :         ContextType context,
     192             :         RunnableType& runnable,
     193             :         TimeoutType& timeout,
     194             :         uint32_t delay,
     195             :         TimeUnitType unit);
     196             : 
     197             :     /**
     198             :      * Schedules a runnable to execute at a fixed rate.
     199             :      *
     200             :      * \param context The task context.
     201             :      * \param runnable The runnable to schedule.
     202             :      * \param timeout The timeout associated with the runnable.
     203             :      * \param delay The delay before the first execution.
     204             :      * \param unit The time unit for the delay.
     205             :      */
     206             :     static void scheduleAtFixedRate(
     207             :         ContextType context,
     208             :         RunnableType& runnable,
     209             :         TimeoutType& timeout,
     210             :         uint32_t delay,
     211             :         TimeUnitType unit);
     212             : 
     213             :     /**
     214             :      * Cancels a scheduled runnable.
     215             :      *
     216             :      * \param timeout The timeout associated with the runnable to cancel.
     217             :      */
     218             :     static void cancel(TimeoutType& timeout);
     219             : 
     220             :     /// Notifies the system of an interrupt entry.
     221             :     static void enterIsr();
     222             : 
     223             :     /// Notifies the system of an interrupt exit.
     224             :     static void leaveIsr();
     225             : 
     226             :     /**
     227             :      * Exits the ISR without yielding control.
     228             :      * \return True if yielding is not required after ISR.
     229             :      */
     230             :     static bool leaveIsrNoYield();
     231             : 
     232             :     /// \return A pointer to the task woken by the ISR.
     233             :     static BaseType_t* getHigherPriorityTaskWoken();
     234             : 
     235             : private:
     236             :     friend struct internal::TaskInitializer<AdapterType>;
     237             : 
     238             :     static void initTask(TaskInitializer& initializer);
     239             : 
     240             :     static void initTask(ContextType context);
     241             : 
     242             :     static void TaskFunction(void* param);
     243             : 
     244             :     static TaskInitializer* _idleTaskInitializer;
     245             :     static TaskInitializer* _timerTaskInitializer;
     246             :     static ::estd::array<TaskContextType, TASK_COUNT> _taskContexts;
     247             : #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE
     248             :     static ::estd::array<::common::AsyncTimeoutManager, TASK_COUNT> _timeoutManagers;
     249             : #endif // ASYNC_TIMEOUTMANAGER2_DISABLE
     250             : #ifndef ASYNC_LOOPER_DISABLE
     251             :     static ::estd::array<::loop::looper, TASK_COUNT> _loopers;
     252             : #endif // ASYNC_LOOPER_DISABLE
     253             :     static ::estd::array<uint32_t, FREERTOS_TASK_COUNT> _stackSizes;
     254             :     static char const* _timerTaskName;
     255             :     static BaseType_t _higherPriorityTaskWokenFlag;
     256             :     static BaseType_t* _higherPriorityTaskWoken;
     257             :     static uint8_t _nestedInterruptCount;
     258             : };
     259             : 
     260             : /**
     261             :  * Inline implementations.
     262             :  */
     263             : template<class Binding>
     264             : typename FreeRtosAdapter<Binding>::TaskInitializer* FreeRtosAdapter<Binding>::_idleTaskInitializer
     265             :     = nullptr;
     266             : template<class Binding>
     267             : typename FreeRtosAdapter<Binding>::TaskInitializer* FreeRtosAdapter<Binding>::_timerTaskInitializer
     268             :     = nullptr;
     269             : template<class Binding>
     270             : ::estd::
     271             :     array<typename FreeRtosAdapter<Binding>::TaskContextType, FreeRtosAdapter<Binding>::TASK_COUNT>
     272             :         FreeRtosAdapter<Binding>::_taskContexts;
     273             : #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE
     274             : template<class Binding>
     275             : ::estd::array<::common::AsyncTimeoutManager, FreeRtosAdapter<Binding>::TASK_COUNT>
     276             :     FreeRtosAdapter<Binding>::_timeoutManagers;
     277             : #endif // ASYNC_TIMEOUTMANAGER2_DISABLE
     278             : #ifndef ASYNC_LOOPER_DISABLE
     279             : template<class Binding>
     280             : ::estd::array<::loop::looper, FreeRtosAdapter<Binding>::TASK_COUNT>
     281             :     FreeRtosAdapter<Binding>::_loopers;
     282             : #endif // ASYNC_LOOPER_DISABLE
     283             : template<class Binding>
     284             : ::estd::array<uint32_t, FreeRtosAdapter<Binding>::FREERTOS_TASK_COUNT>
     285             :     FreeRtosAdapter<Binding>::_stackSizes;
     286             : template<class Binding>
     287             : char const* FreeRtosAdapter<Binding>::_timerTaskName;
     288             : template<class Binding>
     289             : BaseType_t FreeRtosAdapter<Binding>::_higherPriorityTaskWokenFlag = 0;
     290             : template<class Binding>
     291             : BaseType_t* FreeRtosAdapter<Binding>::_higherPriorityTaskWoken = nullptr;
     292             : template<class Binding>
     293             : uint8_t FreeRtosAdapter<Binding>::_nestedInterruptCount = 0U;
     294             : 
     295             : template<class Binding>
     296             : template<ContextType Context>
     297           2 : void FreeRtosAdapter<Binding>::getTaskMemory(
     298             :     StaticTask_t** const ppxTaskTCBBuffer,
     299             :     StackType_t** const ppxTaskStackBuffer,
     300             :     uint32_t* const pulTaskStackSize)
     301             : {
     302           2 :     TaskInitializer& initializer
     303             :         = *((Context == TASK_IDLE) ? _idleTaskInitializer : _timerTaskInitializer);
     304           2 :     estd_assert(ppxTaskTCBBuffer != nullptr);
     305           2 :     estd_assert(ppxTaskStackBuffer != nullptr);
     306           2 :     estd_assert(pulTaskStackSize != nullptr);
     307           2 :     *ppxTaskTCBBuffer   = &initializer._task;
     308           2 :     *ppxTaskStackBuffer = initializer._stack.data();
     309             :     // Conversion to uint32_t is OK, stack will not exceed 4GB.
     310           2 :     *pulTaskStackSize   = static_cast<uint32_t>(initializer._stack.size());
     311           2 : }
     312             : 
     313             : template<class Binding>
     314           3 : inline char const* FreeRtosAdapter<Binding>::getTaskName(size_t const taskIdx)
     315             : {
     316           4 :     return (taskIdx < _taskContexts.size()) ? _taskContexts[taskIdx].getName() : _timerTaskName;
     317             : }
     318             : 
     319             : template<class Binding>
     320           1 : inline TaskHandle_t FreeRtosAdapter<Binding>::getTaskHandle(size_t const taskIdx)
     321             : {
     322           1 :     return _taskContexts[taskIdx].getTaskHandle();
     323             : }
     324             : 
     325             : template<class Binding>
     326             : inline typename FreeRtosAdapter<Binding>::TaskConfigType const*
     327           1 : FreeRtosAdapter<Binding>::getTaskConfig(size_t const taskIdx)
     328             : {
     329           1 :     return TaskConfigsType::getTaskConfig(taskIdx);
     330             : }
     331             : 
     332             : template<class Binding>
     333           7 : ContextType FreeRtosAdapter<Binding>::getCurrentTaskContext()
     334             : {
     335           7 :     if (_higherPriorityTaskWoken == nullptr)
     336             :     {
     337           6 :         return static_cast<ContextType>(uxTaskGetTaskNumber(xTaskGetCurrentTaskHandle()));
     338             :     }
     339             :     return CONTEXT_INVALID;
     340             : }
     341             : 
     342             : template<class Binding>
     343           8 : void FreeRtosAdapter<Binding>::initTask(TaskInitializer& initializer)
     344             : {
     345           8 :     ContextType const context                 = initializer._context;
     346           8 :     _stackSizes[static_cast<size_t>(context)] = static_cast<uint32_t>(
     347           8 :         static_cast<size_t>(initializer._stack.size()) * sizeof(BaseType_t));
     348             :     TaskConfigsType::setTaskConfig(context, initializer._config);
     349           8 :     if (context == TASK_TIMER)
     350             :     {
     351           2 :         _timerTaskInitializer = &initializer;
     352           2 :         _timerTaskName        = initializer._name;
     353             :     }
     354             :     else
     355             :     {
     356           6 :         initTask(context);
     357           6 :         TaskContextType& taskContext = _taskContexts[static_cast<size_t>(context)];
     358           6 :         if (context == TASK_IDLE)
     359             :         {
     360           1 :             _idleTaskInitializer = &initializer;
     361           1 :             taskContext.initTask(TASK_IDLE, initializer._name, initializer._taskFunction);
     362             :         }
     363             :         else
     364             :         {
     365           5 :             taskContext.createTask(
     366             :                 context,
     367           5 :                 initializer._task,
     368             :                 initializer._name,
     369             :                 static_cast<UBaseType_t>(context),
     370           5 :                 initializer._stack,
     371             :                 initializer._taskFunction);
     372             :         }
     373             :     }
     374           8 : }
     375             : 
     376             : template<class Binding>
     377             : void FreeRtosAdapter<Binding>::initTask(ContextType const context)
     378             : {
     379             : #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE
     380             :     _timeoutManagers[static_cast<size_t>(context)].init(context);
     381             : #endif // ASYNC_TIMEOUTMANAGER2_DISABLE
     382             : #ifndef ASYNC_LOOPER_DISABLE
     383             :     _loopers[static_cast<size_t>(context)].init(context);
     384             : #endif // ASYNC_LOOPER_DISABLE
     385             : }
     386             : 
     387             : template<class Binding>
     388           7 : void FreeRtosAdapter<Binding>::init()
     389             : {
     390           7 :     TaskInitializer::run();
     391             : }
     392             : 
     393             : template<class Binding>
     394           1 : void FreeRtosAdapter<Binding>::run()
     395             : {
     396           1 :     vTaskStartScheduler();
     397             : }
     398             : 
     399             : template<class Binding>
     400           1 : void FreeRtosAdapter<Binding>::runningHook()
     401             : {
     402           1 :     _taskContexts[TASK_IDLE].initTaskHandle(xTaskGetIdleTaskHandle());
     403             : }
     404             : 
     405             : template<class Binding>
     406           2 : bool FreeRtosAdapter<Binding>::getStackUsage(size_t const taskIdx, StackUsage& stackUsage)
     407             : {
     408           2 :     if (taskIdx < FREERTOS_TASK_COUNT)
     409             :     {
     410           2 :         stackUsage._stackSize = _stackSizes[taskIdx];
     411           2 :         uint32_t const unusedSize
     412             :             = (taskIdx == TASK_TIMER)
     413           2 :                   ? TaskContextType::getUnusedStackSize(xTimerGetTimerDaemonTaskHandle())
     414           1 :                   : _taskContexts[taskIdx].getUnusedStackSize();
     415           2 :         stackUsage._usedSize = stackUsage._stackSize - unusedSize;
     416           2 :         return true;
     417             :     }
     418             :     return false;
     419             : }
     420             : 
     421             : template<class Binding>
     422           1 : inline void FreeRtosAdapter<Binding>::callIdleTaskFunction()
     423             : {
     424           1 :     _taskContexts[TASK_IDLE].callTaskFunction();
     425             : }
     426             : 
     427             : template<class Binding>
     428           2 : inline void FreeRtosAdapter<Binding>::execute(ContextType const context, RunnableType& runnable)
     429             : {
     430           2 :     _taskContexts[static_cast<size_t>(context)].execute(runnable);
     431             : }
     432             : 
     433             : template<class Binding>
     434           2 : inline void FreeRtosAdapter<Binding>::schedule(
     435             :     ContextType const context,
     436             :     RunnableType& runnable,
     437             :     TimeoutType& timeout,
     438             :     uint32_t const delay,
     439             :     TimeUnitType const unit)
     440             : {
     441           2 :     _taskContexts[static_cast<size_t>(context)].schedule(runnable, timeout, delay, unit);
     442             : }
     443             : 
     444             : template<class Binding>
     445           2 : inline void FreeRtosAdapter<Binding>::scheduleAtFixedRate(
     446             :     ContextType const context,
     447             :     RunnableType& runnable,
     448             :     TimeoutType& timeout,
     449             :     uint32_t const delay,
     450             :     TimeUnitType const unit)
     451             : {
     452           2 :     _taskContexts[static_cast<size_t>(context)].scheduleAtFixedRate(runnable, timeout, delay, unit);
     453             : }
     454             : 
     455             : template<class Binding>
     456           5 : inline void FreeRtosAdapter<Binding>::cancel(TimeoutType& timeout)
     457             : {
     458           5 :     LockType const lock;
     459           5 :     ContextType const context = timeout._context;
     460           5 :     if (context != CONTEXT_INVALID)
     461             :     {
     462           4 :         timeout._context = CONTEXT_INVALID;
     463           9 :         _taskContexts[static_cast<size_t>(context)].cancel(timeout);
     464             :     }
     465           5 : }
     466             : 
     467             : #ifndef ASYNC_LOOPER_DISABLE
     468             : template<class Binding>
     469             : ::loop::looper& FreeRtosAdapter<Binding>::getLooper(ContextType const context)
     470             : {
     471             :     return _loopers[static_cast<size_t>(context)];
     472             : }
     473             : #endif // ASYNC_LOOPER_DISABLE
     474             : 
     475             : #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE
     476             : template<class Binding>
     477             : inline ::common::ITimeoutManager2&
     478             : FreeRtosAdapter<Binding>::getTimeoutManager(ContextType const context)
     479             : {
     480             :     return _timeoutManagers[static_cast<size_t>(context)];
     481             : }
     482             : #endif // ASYNC_TIMEOUTMANAGER2_DISABLE
     483             : 
     484             : template<class Binding>
     485          32 : inline BaseType_t* FreeRtosAdapter<Binding>::getHigherPriorityTaskWoken()
     486             : {
     487          32 :     return _higherPriorityTaskWoken;
     488             : }
     489             : 
     490             : template<class Binding>
     491          10 : inline void FreeRtosAdapter<Binding>::enterIsr()
     492             : {
     493          10 :     internal::NestedInterruptLock<> const lock;
     494          10 :     ++_nestedInterruptCount;
     495          10 :     _higherPriorityTaskWoken = &FreeRtosAdapter::_higherPriorityTaskWokenFlag;
     496          10 : }
     497             : 
     498             : template<class Binding>
     499           5 : inline void FreeRtosAdapter<Binding>::leaveIsr()
     500             : {
     501           5 :     internal::NestedInterruptLock<> const lock;
     502           5 :     --_nestedInterruptCount;
     503           5 :     if (_nestedInterruptCount == 0U)
     504             :     {
     505           4 :         FreeRtosAdapter::_higherPriorityTaskWoken = nullptr;
     506           4 :         if (FreeRtosAdapter::_higherPriorityTaskWokenFlag != pdFALSE)
     507             :         {
     508           1 :             FreeRtosAdapter::_higherPriorityTaskWokenFlag = pdFALSE;
     509           1 :             portYIELD_FROM_ISR(pdTRUE);
     510             :         }
     511             :     }
     512           5 : }
     513             : 
     514             : template<class Binding>
     515           5 : inline bool FreeRtosAdapter<Binding>::leaveIsrNoYield()
     516             : {
     517           5 :     internal::NestedInterruptLock<> const lock;
     518           5 :     --_nestedInterruptCount;
     519           5 :     if (_nestedInterruptCount == 0U)
     520             :     {
     521           4 :         FreeRtosAdapter::_higherPriorityTaskWoken = nullptr;
     522           4 :         if (FreeRtosAdapter::_higherPriorityTaskWokenFlag != pdFALSE)
     523             :         {
     524           2 :             FreeRtosAdapter::_higherPriorityTaskWokenFlag = pdFALSE;
     525           2 :             return true;
     526             :         }
     527             :     }
     528             :     return false;
     529           5 : }
     530             : 
     531             : template<class Binding>
     532           1 : FreeRtosAdapter<Binding>::StackUsage::StackUsage() : _stackSize(0U), _usedSize(0U)
     533             : {}
     534             : 
     535             : namespace internal
     536             : {
     537             : template<size_t N, typename TaskConfig>
     538             : ::estd::array<TaskConfig, N> TaskConfigHolder<N, TaskConfig>::_taskConfigs;
     539             : 
     540             : template<size_t N, typename TaskConfig>
     541           1 : void TaskConfigHolder<N, TaskConfig>::setTaskConfig(
     542             :     size_t const taskIdx, TaskConfigType const& taskConfig)
     543             : {
     544           1 :     _taskConfigs[taskIdx] = taskConfig;
     545             : }
     546             : 
     547             : template<size_t N, typename TaskConfig>
     548           1 : TaskConfig const* TaskConfigHolder<N, TaskConfig>::getTaskConfig(size_t const taskIdx)
     549             : {
     550           1 :     return &_taskConfigs[taskIdx];
     551             : }
     552             : 
     553             : template<size_t N>
     554             : void TaskConfigHolder<N, void>::setTaskConfig(
     555             :     size_t const /*taskIdx*/,
     556             :     typename TaskConfigHolder<N, void>::TaskConfigType const& /*taskConfig*/)
     557             : {}
     558             : 
     559             : template<size_t N>
     560             : typename TaskConfigHolder<N, void>::TaskConfigType const*
     561           1 : TaskConfigHolder<N, void>::getTaskConfig(size_t const /*taskIdx*/)
     562             : {
     563           1 :     estd_assert(false);
     564             :     return nullptr;
     565             : }
     566             : 
     567             : } // namespace internal
     568             : 
     569             : } // namespace async
     570             : 
     571             : #endif // GUARD_DB9C7111_F66E_4D50_B724_5DF992A19ED0

Generated by: LCOV version 1.14