Embedded Template Library 1.0
Loading...
Searching...
No Matches
scheduler.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2017 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#ifndef ETL_SCHEDULER_INCLUDED
30#define ETL_SCHEDULER_INCLUDED
31
32#include "platform.h"
33#include "error_handler.h"
34#include "exception.h"
35#include "function.h"
36#include "nullptr.h"
37#include "task.h"
38#include "type_traits.h"
39#include "vector.h"
40
41#include <stdint.h>
42
43namespace etl
44{
45 //***************************************************************************
47 //***************************************************************************
48 class scheduler_exception : public etl::exception
49 {
50 public:
51
52 scheduler_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
53 : etl::exception(reason_, file_name_, line_number_)
54 {
55 }
56 };
57
58 //***************************************************************************
60 //***************************************************************************
61 class scheduler_no_tasks_exception : public etl::scheduler_exception
62 {
63 public:
64
65 scheduler_no_tasks_exception(string_type file_name_, numeric_type line_number_)
66 : etl::scheduler_exception(ETL_ERROR_TEXT("scheduler:no tasks", ETL_SCHEDULER_FILE_ID"A"), file_name_, line_number_)
67 {
68 }
69 };
70
71 //***************************************************************************
73 //***************************************************************************
74 class scheduler_null_task_exception : public etl::scheduler_exception
75 {
76 public:
77
78 scheduler_null_task_exception(string_type file_name_, numeric_type line_number_)
79 : etl::scheduler_exception(ETL_ERROR_TEXT("scheduler:null task", ETL_SCHEDULER_FILE_ID"B"), file_name_, line_number_)
80 {
81 }
82 };
83
84 //***************************************************************************
86 //***************************************************************************
87 class scheduler_too_many_tasks_exception : public etl::scheduler_exception
88 {
89 public:
90
91 scheduler_too_many_tasks_exception(string_type file_name_, numeric_type line_number_)
92 : etl::scheduler_exception(ETL_ERROR_TEXT("scheduler:too many tasks", ETL_SCHEDULER_FILE_ID"C"), file_name_, line_number_)
93 {
94 }
95 };
96
97 //***************************************************************************
101 //***************************************************************************
103 {
104 bool schedule_tasks(etl::ivector<etl::task*>& task_list)
105 {
106 bool idle = true;
107
108 for (size_t index = 0UL; index < task_list.size(); ++index)
109 {
110 etl::task& task = *(task_list[index]);
111
112 if (task.task_request_work() > 0)
113 {
115 idle = false;
116 }
117 }
118
119 return idle;
120 }
121 };
122
124 ETL_DEPRECATED_REASON("Misspelt class name") typedef scheduler_policy_sequential_single scheduler_policy_sequencial_single;
125
126 //***************************************************************************
130 //***************************************************************************
132 {
133 bool schedule_tasks(etl::ivector<etl::task*>& task_list)
134 {
135 bool idle = true;
136
137 for (size_t index = 0UL; index < task_list.size(); ++index)
138 {
139 etl::task& task = *(task_list[index]);
140
141 while (task.task_request_work() > 0)
142 {
144 idle = false;
145 }
146 }
147
148 return idle;
149 }
150 };
151
153 ETL_DEPRECATED
155
156 //***************************************************************************
160 //***************************************************************************
162 {
163 bool schedule_tasks(etl::ivector<etl::task*>& task_list)
164 {
165 bool idle = true;
166
167 size_t index = 0UL;
168 while (index < task_list.size())
169 {
170 etl::task& task = *(task_list[index]);
171
172 if (task.task_request_work() > 0)
173 {
175 idle = false;
176 break;
177 }
178 else
179 {
180 ++index;
181 }
182 }
183
184 return idle;
185 }
186 };
187
188 //***************************************************************************
193 //***************************************************************************
195 {
196 bool schedule_tasks(etl::ivector<etl::task*>& task_list)
197 {
198 bool idle = true;
199
200 size_t most_index = 0UL;
201 uint32_t most_work = 0UL;
202
203 for (size_t index = 0UL; index < task_list.size(); ++index)
204 {
205 etl::task& task = *(task_list[index]);
206
207 uint32_t n_work = task.task_request_work();
208
209 if (n_work > most_work)
210 {
211 most_index = index;
212 most_work = n_work;
213 idle = false;
214 }
215 }
216
217 if (!idle)
218 {
219 task_list[most_index]->task_process_work();
220 }
221
222 return idle;
223 }
224 };
225
226 //***************************************************************************
228 //***************************************************************************
230 {
231 public:
232
233 //*******************************************
234 // Virtuals.
235 //*******************************************
236 virtual void start() = 0;
237
238 virtual ~ischeduler() {}
239
240 //*******************************************
242 //*******************************************
244 {
245 p_idle_callback = &callback;
246 }
247
248 //*******************************************
250 //*******************************************
252 {
253 p_watchdog_callback = &callback;
254 }
255
256 //*******************************************
258 //*******************************************
259 void set_scheduler_running(bool scheduler_running_)
260 {
261 scheduler_running = scheduler_running_;
262 }
263
264 //*******************************************
266 //*******************************************
268 {
269 return scheduler_running;
270 }
271
272 //*******************************************
274 //*******************************************
276 {
277 scheduler_exit = true;
278 }
279
280 //*******************************************
283 //*******************************************
285 {
286 ETL_ASSERT(!task_list.full(), ETL_ERROR(etl::scheduler_too_many_tasks_exception));
287
288 if (!task_list.full())
289 {
290 typename task_list_t::iterator itask = etl::upper_bound(task_list.begin(), task_list.end(), task.get_task_priority(), compare_priority());
291
292 task_list.insert(itask, &task);
293
295 }
296 }
297
298 //*******************************************
302 //*******************************************
303 template <typename TSize>
304 void add_task_list(etl::task** p_tasks, TSize size)
305 {
306 for (TSize i = 0; i < size; ++i)
307 {
308 ETL_ASSERT((p_tasks[i] != ETL_NULLPTR), ETL_ERROR(etl::scheduler_null_task_exception));
309 add_task(*(p_tasks[i]));
310 }
311 }
312
313 protected:
314
315 //*******************************************
317 //*******************************************
319 : scheduler_running(false)
320 , scheduler_exit(false)
321 , p_idle_callback(ETL_NULLPTR)
322 , p_watchdog_callback(ETL_NULLPTR)
323 , task_list(task_list_)
324 {
325 }
326
327 bool scheduler_running;
328 bool scheduler_exit;
329 etl::ifunction<void>* p_idle_callback;
330 etl::ifunction<void>* p_watchdog_callback;
331
332 private:
333
334 //*******************************************
335 // Used to order tasks in descending priority.
336 //*******************************************
337 struct compare_priority
338 {
339 bool operator()(etl::task_priority_t priority, etl::task* ptask) const
340 {
341 return priority > ptask->get_task_priority();
342 }
343 };
344
345 typedef etl::ivector<etl::task*> task_list_t;
346 task_list_t& task_list;
347 };
348
349 //***************************************************************************
351 //***************************************************************************
352 template <typename TSchedulerPolicy, size_t MAX_TASKS_>
353 class scheduler
354 : public etl::ischeduler
355 , protected TSchedulerPolicy
356 {
357 public:
358
359 enum
360 {
361 MAX_TASKS = MAX_TASKS_,
362 };
363
364 scheduler()
365 : ischeduler(task_list)
366 {
367 }
368
369 //*******************************************
371 //*******************************************
372 void start()
373 {
374 ETL_ASSERT(task_list.size() > 0, ETL_ERROR(etl::scheduler_no_tasks_exception));
375
376 scheduler_running = true;
377
378 while (!scheduler_exit)
379 {
380 if (scheduler_running)
381 {
382 bool idle = TSchedulerPolicy::schedule_tasks(task_list);
383
384 if (p_watchdog_callback)
385 {
386 (*p_watchdog_callback)();
387 }
388
389 if (idle && p_idle_callback)
390 {
391 (*p_idle_callback)();
392 }
393 }
394 }
395 }
396
397 private:
398
399 typedef etl::vector<etl::task*, MAX_TASKS> task_list_t;
400 task_list_t task_list;
401 };
402} // namespace etl
403
404#endif
Definition callback.h:46
Scheduler base.
Definition scheduler.h:230
void add_task_list(etl::task **p_tasks, TSize size)
Definition scheduler.h:304
ischeduler(etl::ivector< etl::task * > &task_list_)
Constructor.
Definition scheduler.h:318
void set_watchdog_callback(etl::ifunction< void > &callback)
Set the watchdog callback.
Definition scheduler.h:251
void exit_scheduler()
Force the scheduler to exit.
Definition scheduler.h:275
void set_scheduler_running(bool scheduler_running_)
Set the running state for the scheduler.
Definition scheduler.h:259
void add_task(etl::task &task)
Definition scheduler.h:284
void set_idle_callback(etl::ifunction< void > &callback)
Set the idle callback.
Definition scheduler.h:243
bool scheduler_is_running() const
Get the running state for the scheduler.
Definition scheduler.h:267
Base exception class for scheduler.
Definition scheduler.h:49
'No tasks' exception.
Definition scheduler.h:62
'Null tasks' exception.
Definition scheduler.h:75
'Too many tasks' exception.
Definition scheduler.h:88
void start()
Start the scheduler.
Definition scheduler.h:372
Task.
Definition task.h:59
virtual void on_task_added()
Called when the task has been added to the scheduler.
Definition task.h:90
virtual uint32_t task_request_work() const =0
etl::task_priority_t get_task_priority() const
Definition task.h:115
virtual void task_process_work()=0
Called to get the task to do work.
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition exception.h:59
Definition function.h:54
size_type size() const
Definition vector.h:1040
Definition vector.h:71
Definition vector.h:1277
bitset_ext
Definition absolute.h:40
ETL_DEPRECATED typedef scheduler_policy_sequential_multiple scheduler_policy_sequencial_multiple
Typedef for backwards compatibility with miss-spelt struct name.
Definition scheduler.h:154
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
ETL_DEPRECATED_REASON("Misspelt class name") typedef scheduler_policy_sequential_single scheduler_policy_sequencial_single
Typedef for backwards compatibility with miss-spelt struct name.
Definition scheduler.h:162
Definition scheduler.h:195
Definition scheduler.h:103