Simple Task Scheduler. For the moment only implements continuous running tasks and periodic tasks.
Example
two blinking leds
#include "mbed.h" #include "task_scheduler.h" Serial pc(USBTX, USBRX); // tx, r class Foo { DigitalOut myled1; int counter; public: Foo(void) :myled1(LED1) { counter = 0; } void alive_task(void) { if (counter++ % 30000 == 0) { myled1 = !myled1; } } }; class Bar { DigitalOut myled2; public: Bar(void) :myled2(LED2) {} void control_task(void) { myled2 = !myled2; } }; int main() { Foo foo; Bar bar; SimpleTaskScheduler::TaskScheduler scheduler; scheduler.create_continuous_task(&foo, &Foo::alive_task); scheduler.create_periodic_task(&bar, &Bar::control_task, 1); while(1) { scheduler.update(); } }
Revision 3:bd96023168df, committed 2016-12-13
- Comitter:
- dwini
- Date:
- Tue Dec 13 14:48:48 2016 +0100
- Parent:
- 2:1d20f2b3c788
- Commit message:
- Refactor and allow starting and stopping of tasks.
Changed in this revision
--- a/task_scheduler.cpp Wed Jul 13 09:01:16 2016 +0000 +++ b/task_scheduler.cpp Tue Dec 13 14:48:48 2016 +0100 @@ -16,7 +16,23 @@ } } - int TaskScheduler::add_task(Task * task) { + void TaskScheduler::stop_task(unsigned int id) { + for (unsigned int i = 0; i < tasks.size(); i++) { + if (tasks[i]->get_id() == id) { + tasks[i]->stop(); + } + } + } + + void TaskScheduler::start_task(unsigned int id) { + for (unsigned int i = 0; i < tasks.size(); i++) { + if (tasks[i]->get_id() == id) { + tasks[i]->start(); + } + } + } + + unsigned int TaskScheduler::add_task(Task * task) { tasks.push_back(task); return task->get_id(); }
--- a/task_scheduler.h Wed Jul 13 09:01:16 2016 +0000 +++ b/task_scheduler.h Tue Dec 13 14:48:48 2016 +0100 @@ -1,7 +1,7 @@ #pragma once #include <vector> -#include "task.h" +#include "continuous_task.h" #include "periodic_task.h" // Definition of template methods need to be inside header file. @@ -20,20 +20,22 @@ public: void update(void); + void stop_task(unsigned int id); + void start_task(unsigned int id); public: - template<typename T> int create_continuous_task(T* object, void (T::*method)(void)) { - Task * task = new Task(object, method); + template<typename T> unsigned int create_continuous_task(T* object, void (T::*method)(void)) { + Task * task = new ContinuousTask(object, method); return add_task(task); } - template<typename T> int create_periodic_task(T* object, void (T::*method)(void), float period_seconds) { + template<typename T> unsigned int create_periodic_task(T* object, void (T::*method)(void), float period_seconds) { Task * task = new PeriodicTask(object, method, period_seconds); return add_task(task); } private: - int add_task(Task * task); + unsigned int add_task(Task * task); }; };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tasks/continuous_task.cpp Tue Dec 13 14:48:48 2016 +0100 @@ -0,0 +1,16 @@ +#include "continuous_task.h" + +namespace SimpleTaskScheduler { + + void ContinuousTask::run(void) { + if (nextState == SHOULD_RUN) { + state = RUNNING; + this->call(); + state = WAITING; + } + } + + void ContinuousTask::start(void) { + nextState = SHOULD_RUN; + } +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tasks/continuous_task.h Tue Dec 13 14:48:48 2016 +0100 @@ -0,0 +1,22 @@ +#pragma once + +#include "task.h" + +// Definition of template methods need to be inside header file. +// http://stackoverflow.com/questions/8752837/undefined-reference-to-template-class-constructor + +namespace SimpleTaskScheduler { + + class ContinuousTask : public Task { + + public: + template<typename T> ContinuousTask(T* object, void (T::*method)(void)) : Task(object, method) { + state = WAITING; + nextState = SHOULD_RUN; + } + + public: + virtual void run(void); + virtual void start(void); + }; +};
--- a/tasks/periodic_task.cpp Wed Jul 13 09:01:16 2016 +0000 +++ b/tasks/periodic_task.cpp Tue Dec 13 14:48:48 2016 +0100 @@ -2,17 +2,19 @@ namespace SimpleTaskScheduler { - void PeriodicTask::run(void) { - if (state == SHOULD_RUN) { + void PeriodicTask::run(void) { + if (nextState == SHOULD_RUN) { state = RUNNING; - this->callback.call(); + this->call(); state = WAITING; + nextState = WAITING; } } void PeriodicTask::tick(void) { - // Following can mess with your day if your task is long and periodic periodic - //period is small. - state = SHOULD_RUN; + // Following can mess with your day if task is long and period is small + if (nextState == WAITING) { + nextState = SHOULD_RUN; + } } };
--- a/tasks/periodic_task.h Wed Jul 13 09:01:16 2016 +0000 +++ b/tasks/periodic_task.h Tue Dec 13 14:48:48 2016 +0100 @@ -1,6 +1,5 @@ #pragma once -#include "mbed.h" #include "task.h" // Definition of template methods need to be inside header file. @@ -14,11 +13,9 @@ Ticker ticker; public: - PeriodicTask(float period_seconds); - - public: template<typename T> PeriodicTask(T* object, void (T::*method)(void), float period_seconds) : Task(object, method) { state = WAITING; + nextState = WAITING; ticker.attach(this, &PeriodicTask::tick, period_seconds); }
--- a/tasks/task.cpp Wed Jul 13 09:01:16 2016 +0000 +++ b/tasks/task.cpp Tue Dec 13 14:48:48 2016 +0100 @@ -2,19 +2,19 @@ namespace SimpleTaskScheduler { - int Task::get_id(void) { return this->id; } - int Task::get_state(void) { return this->state; } + unsigned int Task::get_id(void) { return this->id; } + void Task::call(void) { this->callback.call(); } - int Task::generate_id(void) { + unsigned int Task::generate_id(void) { static int numberOfInstances = 0; return numberOfInstances++; } - void Task::run(void) { - if (state == SHOULD_RUN) { - state = RUNNING; - this->callback.call(); - state = SHOULD_RUN; - } + void Task::stop(void) { + nextState = STOPPED; + } + + void Task::start(void) { + nextState = WAITING; } };
--- a/tasks/task.h Wed Jul 13 09:01:16 2016 +0000 +++ b/tasks/task.h Tue Dec 13 14:48:48 2016 +0100 @@ -12,35 +12,35 @@ class Task { public: - int get_id(void); - int get_state(void); + unsigned int get_id(void); private: - int id; + unsigned int id; + + private: + Callback<void()> callback; protected: - FunctionPointer callback; // from mbed TaskState state; - - // Think we will need this for periodic task as we will influence state from outside - // night run bad if task is already in running state and we change from isr to should_run - // bool requesting_execution; - - public: - Task(void); + TaskState nextState; public: template<typename T> Task(T* object, void (T::*method)(void)) { this->callback.attach(object, method); id = generate_id(); - state = SHOULD_RUN; + nextState = state = WAITING; // Subclass should set correct state } public: - virtual void run(void); + virtual void run(void) = 0; + virtual void stop(void); + virtual void start(void); + + protected: + void call(void); private: - int generate_id(void); + unsigned int generate_id(void); }; };