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();
    }
}

Files at this revision

API Documentation at this revision

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

task_scheduler.cpp Show annotated file Show diff for this revision Revisions of this file
task_scheduler.h Show annotated file Show diff for this revision Revisions of this file
tasks/continuous_task.cpp Show annotated file Show diff for this revision Revisions of this file
tasks/continuous_task.h Show annotated file Show diff for this revision Revisions of this file
tasks/periodic_task.cpp Show annotated file Show diff for this revision Revisions of this file
tasks/periodic_task.h Show annotated file Show diff for this revision Revisions of this file
tasks/task.cpp Show annotated file Show diff for this revision Revisions of this file
tasks/task.h Show annotated file Show diff for this revision Revisions of this file
--- 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);
 
   };
 };