Embedded Template Library 1.0
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 "vector.h"
34#include "nullptr.h"
35#include "error_handler.h"
36#include "exception.h"
37#include "task.h"
38#include "type_traits.h"
39#include "function.h"
40
41#include <stdint.h>
42
43namespace etl
44{
45 //***************************************************************************
47 //***************************************************************************
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 //***************************************************************************
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 //***************************************************************************
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 //***************************************************************************
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
154
155 //***************************************************************************
159 //***************************************************************************
161 {
162 bool schedule_tasks(etl::ivector<etl::task*>& task_list)
163 {
164 bool idle = true;
165
166 size_t index = 0UL;
167 while (index < task_list.size())
168 {
169 etl::task& task = *(task_list[index]);
170
171 if (task.task_request_work() > 0)
172 {
174 idle = false;
175 break;
176 }
177 else
178 {
179 ++index;
180 }
181 }
182
183 return idle;
184 }
185 };
186
187 //***************************************************************************
192 //***************************************************************************
194 {
195 bool schedule_tasks(etl::ivector<etl::task*>& task_list)
196 {
197 bool idle = true;
198
199 size_t most_index = 0UL;
200 uint32_t most_work = 0UL;
201
202 for (size_t index = 0UL; index < task_list.size(); ++index)
203 {
204 etl::task& task = *(task_list[index]);
205
206 uint32_t n_work = task.task_request_work();
207
208 if (n_work > most_work)
209 {
210 most_index = index;
211 most_work = n_work;
212 idle = false;
213 }
214 }
215
216 if (!idle)
217 {
218 task_list[most_index]->task_process_work();
219 }
220
221 return idle;
222 }
223 };
224
225 //***************************************************************************
227 //***************************************************************************
229 {
230 public:
231
232 //*******************************************
233 // Virtuals.
234 //*******************************************
235 virtual void start() = 0;
236
237 virtual ~ischeduler()
238 {
239 }
240
241 //*******************************************
243 //*******************************************
245 {
246 p_idle_callback = &callback;
247 }
248
249 //*******************************************
251 //*******************************************
253 {
254 p_watchdog_callback = &callback;
255 }
256
257 //*******************************************
259 //*******************************************
260 void set_scheduler_running(bool scheduler_running_)
261 {
262 scheduler_running = scheduler_running_;
263 }
264
265 //*******************************************
267 //*******************************************
269 {
270 return scheduler_running;
271 }
272
273 //*******************************************
275 //*******************************************
277 {
278 scheduler_exit = true;
279 }
280
281 //*******************************************
284 //*******************************************
286 {
288
289 if (!task_list.full())
290 {
291 typename task_list_t::iterator itask = etl::upper_bound(task_list.begin(),
292 task_list.end(),
294 compare_priority());
295
296 task_list.insert(itask, &task);
297
299 }
300 }
301
302 //*******************************************
306 //*******************************************
307 template <typename TSize>
308 void add_task_list(etl::task** p_tasks, TSize size)
309 {
310 for (TSize i = 0; i < size; ++i)
311 {
312 ETL_ASSERT((p_tasks[i] != ETL_NULLPTR), ETL_ERROR(etl::scheduler_null_task_exception));
313 add_task(*(p_tasks[i]));
314 }
315 }
316
317 protected:
318
319 //*******************************************
321 //*******************************************
323 : scheduler_running(false),
324 scheduler_exit(false),
325 p_idle_callback(ETL_NULLPTR),
326 p_watchdog_callback(ETL_NULLPTR),
327 task_list(task_list_)
328 {
329 }
330
331 bool scheduler_running;
332 bool scheduler_exit;
333 etl::ifunction<void>* p_idle_callback;
334 etl::ifunction<void>* p_watchdog_callback;
335
336 private:
337
338 //*******************************************
339 // Used to order tasks in descending priority.
340 //*******************************************
341 struct compare_priority
342 {
343 bool operator()(etl::task_priority_t priority, etl::task* ptask) const
344 {
345 return priority > ptask->get_task_priority();
346 }
347 };
348
349 typedef etl::ivector<etl::task*> task_list_t;
350 task_list_t& task_list;
351 };
352
353 //***************************************************************************
355 //***************************************************************************
356 template <typename TSchedulerPolicy, size_t MAX_TASKS_>
357 class scheduler : public etl::ischeduler, protected TSchedulerPolicy
358 {
359 public:
360
361 enum
362 {
363 MAX_TASKS = MAX_TASKS_,
364 };
365
366 scheduler()
367 : ischeduler(task_list)
368 {
369 }
370
371 //*******************************************
373 //*******************************************
374 void start()
375 {
376 ETL_ASSERT(task_list.size() > 0, ETL_ERROR(etl::scheduler_no_tasks_exception));
377
378 scheduler_running = true;
379
380 while (!scheduler_exit)
381 {
382 if (scheduler_running)
383 {
384 bool idle = TSchedulerPolicy::schedule_tasks(task_list);
385
386 if (p_watchdog_callback)
387 {
388 (*p_watchdog_callback)();
389 }
390
391 if (idle && p_idle_callback)
392 {
393 (*p_idle_callback)();
394 }
395 }
396 }
397 }
398
399 private:
400
401 typedef etl::vector<etl::task*, MAX_TASKS> task_list_t;
402 task_list_t task_list;
403 };
404}
405
406#endif
Definition: callback.h:45
Scheduler base.
Definition: scheduler.h:229
void add_task_list(etl::task **p_tasks, TSize size)
Definition: scheduler.h:308
ischeduler(etl::ivector< etl::task * > &task_list_)
Constructor.
Definition: scheduler.h:322
void set_watchdog_callback(etl::ifunction< void > &callback)
Set the watchdog callback.
Definition: scheduler.h:252
void exit_scheduler()
Force the scheduler to exit.
Definition: scheduler.h:276
void set_scheduler_running(bool scheduler_running_)
Set the running state for the scheduler.
Definition: scheduler.h:260
void add_task(etl::task &task)
Definition: scheduler.h:285
void set_idle_callback(etl::ifunction< void > &callback)
Set the idle callback.
Definition: scheduler.h:244
bool scheduler_is_running() const
Get the running state for the scheduler.
Definition: scheduler.h:268
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
Scheduler.
Definition: scheduler.h:358
void start()
Start the scheduler.
Definition: scheduler.h:374
Task.
Definition: task.h:59
virtual void on_task_added()
Called when the task has been added to the scheduler.
Definition: task.h:92
virtual uint32_t task_request_work() const =0
etl::task_priority_t get_task_priority() const
Definition: task.h:117
virtual void task_process_work()=0
Called to get the task to do work.
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
Definition: exception.h:47
Definition: function.h:73
iterator begin()
Definition: vector.h:100
iterator end()
Definition: vector.h:118
bool full() const
Definition: vector.h:977
size_type size() const
Definition: vector.h:959
iterator insert(const_iterator position, const_reference value)
Definition: vector.h:560
bitset_ext
Definition: absolute.h:38
ETL_DEPRECATED typedef scheduler_policy_sequential_multiple scheduler_policy_sequencial_multiple
Typedef for backwards compatibility with miss-spelt struct name.
Definition: scheduler.h:153
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:161
Definition: scheduler.h:194
Definition: scheduler.h:103