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