Skyward boardcore
Loading...
Searching...
No Matches
TaskScheduler.h
Go to the documentation of this file.
1/* Copyright (c) 2015-2016 Skyward Experimental Rocketry
2 * Authors: Alain Carlucci, Federico Terraneo, Matteo Piazzolla
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <ActiveObject.h>
26#include <Singleton.h>
27#include <debug/debug.h>
29#include <units/Frequency.h>
30#include <utils/KernelTime.h>
31#include <utils/Stats/Stats.h>
32
33#include <chrono>
34#include <cstdint>
35#include <functional>
36#include <list>
37#include <map>
38#include <queue>
39
40#include "TaskSchedulerData.h"
41
42namespace Boardcore
43{
44
64{
65public:
66 using function_t = std::function<void()>;
67
71 static constexpr size_t MAX_TASKS = 256;
72
96 enum class Policy : uint8_t
97 {
98 ONE_SHOT,
99 SKIP, // Skips lost executions and stays aligned with the original
100 // start time.
101 RECOVER
102 };
103
104 explicit TaskScheduler(miosix::Priority priority = miosix::PRIORITY_MAX -
105 1);
106
123 size_t addTask(function_t function, uint32_t periodMs,
124 Policy policy = Policy::RECOVER,
125 int64_t startTick = Kernel::getOldTick())
126 {
127 auto period = std::chrono::milliseconds{periodMs};
128 auto startTime = std::chrono::time_point<std::chrono::steady_clock>{
129 std::chrono::milliseconds{startTick}};
130
131 return addTask(function, period, policy, startTime);
132 }
133
150 size_t addTask(function_t function, Units::Frequency::Hertz frequency,
151 Policy policy = Policy::RECOVER,
152 std::chrono::time_point<std::chrono::steady_clock>
153 startTime = std::chrono::steady_clock::now())
154 {
155 auto period = std::chrono::nanoseconds{
156 static_cast<int64_t>(sToNs(1) / frequency.value())};
157
158 return addTask(function, period, policy, startTime);
159 }
160
177 size_t addTask(function_t function, std::chrono::nanoseconds period,
178 Policy policy = Policy::RECOVER,
179 std::chrono::time_point<std::chrono::steady_clock>
180 startTime = std::chrono::steady_clock::now());
181
185 void enableTask(size_t id);
186
190 void disableTask(size_t id);
191
192 bool start() override;
193
194 void stop() override;
195
196 std::vector<TaskStatsResult> getTaskStats();
197
198private:
199 struct Task
200 {
201 function_t function;
202 int64_t period;
203 int64_t startTime;
205 bool enabled;
206 Policy policy;
207 int64_t lastCall;
208 Stats activationStats;
209 Stats periodStats;
210 Stats workloadStats;
211 uint32_t missedEvents;
212 uint32_t failedEvents;
213
217 Task();
218
227 explicit Task(function_t function, int64_t period, Policy policy,
228 int64_t startTime);
229
230 // Delete copy constructor and copy assignment operator to avoid copying
231 // and force moving
232 Task(const Task& other) = delete;
233 Task& operator=(const Task& other) = delete;
234
235 // Define a move constructor and a move assignment operator to avoid
236 // copying std::function
237 Task(Task&& other) = default;
238 Task& operator=(Task&& other) = default;
239
243 bool empty() const { return !function; }
244 };
245
246 struct Event
247 {
248 size_t taskId;
249 int64_t nextTime;
250
251 Event(size_t taskId, int64_t nextTime)
252 : taskId(taskId), nextTime(nextTime)
253 {
254 }
255
262 bool operator>(const Event& other) const
263 {
264 return this->nextTime > other.nextTime;
265 }
266 };
267
268 // Use `std::greater` as the comparator to have elements with the lowest
269 // time first. Requires operator `>` to be defined for Event.
270 using EventQueue =
271 std::priority_queue<Event, std::vector<Event>, std::greater<Event>>;
272
277 static EventQueue makeAgenda();
278
286 void populateAgenda();
287
288 void run() override;
289
299 void updateStats(const Event& event, int64_t startTime, int64_t endTime);
300
312 void enqueue(Event event, int64_t startTime);
313
314 static TaskStatsResult fromTaskIdPairToStatsResult(const Task& task,
315 size_t id)
316 {
317 return TaskStatsResult{id,
318 std::chrono::nanoseconds{task.period},
319 task.activationStats.getStats(),
320 task.periodStats.getStats(),
321 task.workloadStats.getStats(),
322 task.missedEvents,
323 task.failedEvents};
324 }
325
326 miosix::FastMutex mutex;
327 std::vector<Task> tasks;
329 miosix::ConditionVariable condvar;
330 EventQueue agenda;
331
332 PrintLogger logger = Logging::getLogger("taskscheduler");
333};
334
335} // namespace Boardcore
static PrintLogger getLogger(const string &name)
Computes on-line statistics of a dataset.
Definition Stats.h:54
The Task Scheduler allow to manage simple tasks with a single thread. All the task added must not tak...
std::vector< TaskStatsResult > getTaskStats()
void enableTask(size_t id)
Enables the task with the given id.
bool start() override
Start the thread associated with this active object.
size_t addTask(function_t function, Units::Frequency::Hertz frequency, Policy policy=Policy::RECOVER, std::chrono::time_point< std::chrono::steady_clock > startTime=std::chrono::steady_clock::now())
Add a task function with the given frequency to the scheduler with an auto generated ID.
void disableTask(size_t id)
Disables the task with the given id, preventing it from executing.
Policy
Task behavior policy. Determines the behavior of the scheduler for a specific task.
@ ONE_SHOT
Run the task one single timer.
@ RECOVER
Prioritize the number of executions over the period.
void stop() override
Signals the runner thread to terminate and joins the thread.
size_t addTask(function_t function, uint32_t periodMs, Policy policy=Policy::RECOVER, int64_t startTick=Kernel::getOldTick())
Add a millisecond-period task function to the scheduler with an auto generated ID.
std::function< void()> function_t
TaskScheduler(miosix::Priority priority=miosix::PRIORITY_MAX - 1)
size_t addTask(function_t function, std::chrono::nanoseconds period, Policy policy=Policy::RECOVER, std::chrono::time_point< std::chrono::steady_clock > startTime=std::chrono::steady_clock::now())
Add a task function with the given period to the scheduler with an auto generated ID.
static constexpr size_t MAX_TASKS
The maximum number of tasks the scheduler can handle.
constexpr float value() const
Return the value of the unit in the target ratio.
Definition Units.h:76
long long getOldTick()
Get the current time in milliseconds.
Definition KernelTime.h:43
This file includes all the types the logdecoder script will decode.
uint8_t Event
Definition Event.h:30
constexpr long long sToNs(long long s)
Convert seconds to nanoseconds.
Definition TimeUtils.h:64