Very simple cooperative round-robin task scheduler. See examples.

Dependents:   Garage_Control

Revision:
0:564dd7a5d307
Child:
1:f043501c4bed
diff -r 000000000000 -r 564dd7a5d307 SimpleScheduler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleScheduler.h	Fri Mar 04 10:04:17 2011 +0000
@@ -0,0 +1,209 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+    
+    @file          SimpleScheduler.h 
+    @purpose       Simple round-robin cooperative scheduler
+    @version       see ChangeLog.c
+    @date          Mar 2011
+    @author        Andy Kirkham
+*/
+
+
+#include "mbed.h"
+#include <list>
+#include "STcallback.h"
+
+namespace AjK {
+
+/** SimpleTask
+ *
+ * A defined function task requires a "holder" for SimpleScheduler
+ * to manage it. This is the holder class.
+ *
+ * @see SimpleScheduler
+ * @see example1.h
+ * @see example2.h
+ * @see http://mbed.org/cookbook/SimpleScheduler
+ *
+ * @code
+ *     SimpleTask *task = new SimpleTask(100);
+ *     task->attach(func);
+ * @endcode
+ * @code
+ *     SimpleTask *task = new SimpleTask(100, func);
+ * @endcode
+ */
+class SimpleTask {
+public:
+
+    friend class SimpleScheduler;
+    
+    void attach(void (*fptr)(SimpleTask *pST)) {        
+        _callback->attach(fptr);
+    }
+    
+    template<typename T>
+    void attach(T* tptr, void (T::*mptr)(SimpleTask *pST)) {  
+        if((mptr != NULL) && (tptr != NULL)) { 
+            _callback->attach(tptr, mptr);
+        }        
+    }
+    
+    bool suspend(bool b) {
+        bool prev = _suspended;
+        _suspended = b;
+        return prev;
+    }
+    
+    SimpleTask() { init(); }
+    
+    // Constructor with frequency in miliseconds
+    SimpleTask(int f) { init(f); }
+    
+    // Constructor with frequency in miliseconds
+    SimpleTask(double f) { init(1000.0 * f); }
+    
+    // Constructor with frequency in miliseconds and function
+    SimpleTask(int f, void (*fptr)(SimpleTask *pST)) { 
+        init(f); 
+        _callback->attach(fptr);
+    }
+    
+    // Constructor with frequency in miliseconds and obj/method
+    template<typename T>
+    SimpleTask(int f, T* tptr, void (T::*mptr)(SimpleTask *pST)) {  
+        init(f);
+        if((mptr != NULL) && (tptr != NULL)) { 
+            _callback->attach(tptr, mptr);
+        }        
+    }
+    
+    // Constructor with frequency in miliseconds and function to call
+    SimpleTask(double f, void (*fptr)(SimpleTask *pST)) { 
+        init(f * 1000.0); 
+        _callback->attach(fptr);
+    }
+    
+    // Constructor with frequency in miliseconds and obj/method to call
+    template<typename T>
+    SimpleTask(double f, T* tptr, void (T::*mptr)(SimpleTask *pST)) {  
+        init(f * 1000.0);
+        if((mptr != NULL) && (tptr != NULL)) { 
+            _callback->attach(tptr, mptr);
+        }        
+    }
+    
+    ~SimpleTask() { 
+        delete(_callback);
+    }
+    
+protected:
+    STcallback      *_callback;
+    uint32_t        _counter;
+    uint32_t        _reload;
+    bool            _suspended;
+    
+    void init(int f = 0) {
+        _counter = f;
+        _reload = f;
+        _suspended = false;
+        _callback = new STcallback;
+    }
+};
+
+/** SimpleScheduler
+ *
+ * Manages a set of function or class.methods as tasks to
+ * be called at a scheduled frquency. Simple round-robin
+ * task caller. Note, it's cooperative. That means your
+ * task functions must return BEFORE another task can be
+ * called.
+ *
+ * @see http://mbed.org/cookbook/SimpleScheduler
+ * @see example1.h
+ * @see example2.h
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SimpleScheduler.h"
+ * 
+ * DigitalOut led1(LED1);
+ * DigitalOut led2(LED2);
+ * 
+ * void f1(SimpleTask *task) { led1 = !led1; }
+ * void f2(SimpleTask *task) { led2 = !led2; }
+ * 
+ * SimpleScheduler *scheduler;
+ * 
+ * int main() {
+ * 
+ *     scheduler = new SimpleScheduler;
+ *     
+ *     scheduler
+ *         ->addTask( new SimpleTask(0,   f1) )
+ *         ->addTask( new SimpleTask(200, f2) )
+ *     ;
+ *     
+ *     scheduler->run();    
+ * }
+ * @endcode
+ */
+class SimpleScheduler {
+protected:
+    Ticker _tick;
+    list<SimpleTask *> _tasks;
+    list<SimpleTask *>::iterator _itor;
+    
+    friend class Ticker;
+    
+    void ticktock(void) {
+        for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) {
+            if ((*itor)->_counter && !(*itor)->_suspended) {
+                (*itor)->_counter--;
+            }                
+        }
+    }
+     
+public:
+    
+    SimpleScheduler * addTask(SimpleTask *t) {
+        _tasks.push_back(t);
+        return this;
+    }
+    
+    void run(void) {        
+        _tick.attach_us(this, &SimpleScheduler::ticktock, 1000);
+        while(1) {
+            for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) {
+                if((*itor)->_counter == 0) {
+                    (*itor)->_counter = (*itor)->_reload;
+                    if (!(*itor)->_suspended) {
+                        (*itor)->_callback->call();  
+                    }                  
+                }
+            }
+        }
+    }
+};
+
+}; // namespace AjK ends.
+
+using namespace AjK;