diff --git a/src/shared/scheduler/TaskScheduler.cpp b/src/shared/scheduler/TaskScheduler.cpp index dbdca6f524614045290e30122cc24ff40209d901..5b41ac35ce8f8ddb57bf53bd63113eb1116e9ca1 100644 --- a/src/shared/scheduler/TaskScheduler.cpp +++ b/src/shared/scheduler/TaskScheduler.cpp @@ -63,14 +63,14 @@ size_t TaskScheduler::addTask(function_t function, uint32_t period, // Find a suitable id for the new task for (; id < TASKS_SIZE; id++) { - if ((*tasks)[id].valid == false) + if ((*tasks)[id].empty()) { break; } } // Check if in the corresponding id there's already a task - if ((*tasks)[id].valid) + if ((*tasks)[id].enabled) { // Unlock the mutex for expensive operation Unlock<FastMutex> unlock(mutex); @@ -94,6 +94,44 @@ size_t TaskScheduler::addTask(function_t function, uint32_t period, return id; } +void TaskScheduler::enableTask(size_t id) +{ + if (id > TASKS_SIZE) + { + LOG_ERR(logger, "Tried to enable an out-of-range task, id = {}", id); + return; + } + + Lock<FastMutex> lock(mutex); + Task& task = (*tasks)[id]; + + // Check that the task function is not empty + // Attempting to run an empty function will throw a bad_function_call + // exception + if (task.empty()) + { + // Unlock the mutex to release the scheduler resources before logging + Unlock<FastMutex> unlock(mutex); + LOG_WARN(logger, "Tried to enable an empty task, id = {}", id); + return; + } + + task.enabled = true; + agenda.emplace(id, getTick() + task.period * Constants::TICKS_PER_MS); +} + +void TaskScheduler::disableTask(size_t id) +{ + if (id > TASKS_SIZE) + { + LOG_ERR(logger, "Tried to disable an out-of-range task, id = {}", id); + return; + } + + Lock<FastMutex> lock(mutex); + (*tasks)[id].enabled = false; +} + bool TaskScheduler::start() { // This check is necessary to prevent task normalization if the scheduler is @@ -126,7 +164,7 @@ vector<TaskStatsResult> TaskScheduler::getTaskStats() for (size_t id = 1; id < TASKS_SIZE; id++) { const Task& task = (*tasks)[id]; - if (task.valid) + if (task.enabled) { result.push_back(fromTaskIdPairToStatsResult(task, id)); } @@ -189,7 +227,7 @@ void TaskScheduler::run() agenda.pop(); // Execute the task function - if (nextTask.valid) + if (nextTask.enabled) { { Unlock<FastMutex> unlock(lock); @@ -249,7 +287,7 @@ void TaskScheduler::enqueue(Event event, int64_t startTick) case Policy::ONE_SHOT: // If the task is one shot we won't push it to the agenda and we'll // remove it from the tasks map. - task.valid = false; + task.enabled = false; return; case Policy::SKIP: // Updated the missed events count @@ -276,14 +314,14 @@ void TaskScheduler::enqueue(Event event, int64_t startTick) } TaskScheduler::Task::Task() - : function(nullptr), period(0), valid(false), policy(Policy::SKIP), + : function(nullptr), period(0), enabled(false), policy(Policy::SKIP), lastCall(-1), activationStats(), periodStats(), workloadStats(), missedEvents(0), failedEvents(0) { } TaskScheduler::Task::Task(function_t function, uint32_t period, Policy policy) - : function(function), period(period), valid(true), policy(policy), + : function(function), period(period), enabled(true), policy(policy), lastCall(-1), activationStats(), periodStats(), workloadStats(), missedEvents(0), failedEvents(0) { diff --git a/src/shared/scheduler/TaskScheduler.h b/src/shared/scheduler/TaskScheduler.h index 0130a6dee19950536a4cd86e8475d882bdae25e8..b4a27593903d4661ef5740d3a66efd955aad22c3 100644 --- a/src/shared/scheduler/TaskScheduler.h +++ b/src/shared/scheduler/TaskScheduler.h @@ -29,6 +29,7 @@ #include <utils/Stats/Stats.h> #include <cstdint> +#include <functional> #include <list> #include <map> #include <queue> @@ -119,6 +120,16 @@ public: Policy policy = Policy::SKIP, int64_t startTick = miosix::getTick()); + /** + * @brief Enables the task with the given id. + */ + void enableTask(size_t id); + + /** + * @brief Disables the task with the given id, preventing it from executing. + */ + void disableTask(size_t id); + bool start() override; void stop() override; @@ -136,7 +147,7 @@ private: { function_t function; uint32_t period; // [ms] - bool valid; + bool enabled; ///< Whether the task should be executed. Policy policy; int64_t lastCall; ///< Last activation tick for statistics computation. Stats activationStats; ///< Stats about activation tick error. @@ -168,6 +179,11 @@ private: // copying std::function Task(Task&& other) = default; Task& operator=(Task&& other) = default; + + /** + * @brief Checks if this task is empty. + */ + bool empty() const { return !function; } }; struct Event