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

Dependents:   Garage_Control

Committer:
AjK
Date:
Fri Mar 04 10:04:17 2011 +0000
Revision:
0:564dd7a5d307
Child:
1:f043501c4bed
1.0 See ChangeLog.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:564dd7a5d307 1 /*
AjK 0:564dd7a5d307 2 Copyright (c) 2010 Andy Kirkham
AjK 0:564dd7a5d307 3
AjK 0:564dd7a5d307 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 0:564dd7a5d307 5 of this software and associated documentation files (the "Software"), to deal
AjK 0:564dd7a5d307 6 in the Software without restriction, including without limitation the rights
AjK 0:564dd7a5d307 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 0:564dd7a5d307 8 copies of the Software, and to permit persons to whom the Software is
AjK 0:564dd7a5d307 9 furnished to do so, subject to the following conditions:
AjK 0:564dd7a5d307 10
AjK 0:564dd7a5d307 11 The above copyright notice and this permission notice shall be included in
AjK 0:564dd7a5d307 12 all copies or substantial portions of the Software.
AjK 0:564dd7a5d307 13
AjK 0:564dd7a5d307 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 0:564dd7a5d307 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 0:564dd7a5d307 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 0:564dd7a5d307 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 0:564dd7a5d307 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 0:564dd7a5d307 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 0:564dd7a5d307 20 THE SOFTWARE.
AjK 0:564dd7a5d307 21
AjK 0:564dd7a5d307 22 @file SimpleScheduler.h
AjK 0:564dd7a5d307 23 @purpose Simple round-robin cooperative scheduler
AjK 0:564dd7a5d307 24 @version see ChangeLog.c
AjK 0:564dd7a5d307 25 @date Mar 2011
AjK 0:564dd7a5d307 26 @author Andy Kirkham
AjK 0:564dd7a5d307 27 */
AjK 0:564dd7a5d307 28
AjK 0:564dd7a5d307 29
AjK 0:564dd7a5d307 30 #include "mbed.h"
AjK 0:564dd7a5d307 31 #include <list>
AjK 0:564dd7a5d307 32 #include "STcallback.h"
AjK 0:564dd7a5d307 33
AjK 0:564dd7a5d307 34 namespace AjK {
AjK 0:564dd7a5d307 35
AjK 0:564dd7a5d307 36 /** SimpleTask
AjK 0:564dd7a5d307 37 *
AjK 0:564dd7a5d307 38 * A defined function task requires a "holder" for SimpleScheduler
AjK 0:564dd7a5d307 39 * to manage it. This is the holder class.
AjK 0:564dd7a5d307 40 *
AjK 0:564dd7a5d307 41 * @see SimpleScheduler
AjK 0:564dd7a5d307 42 * @see example1.h
AjK 0:564dd7a5d307 43 * @see example2.h
AjK 0:564dd7a5d307 44 * @see http://mbed.org/cookbook/SimpleScheduler
AjK 0:564dd7a5d307 45 *
AjK 0:564dd7a5d307 46 * @code
AjK 0:564dd7a5d307 47 * SimpleTask *task = new SimpleTask(100);
AjK 0:564dd7a5d307 48 * task->attach(func);
AjK 0:564dd7a5d307 49 * @endcode
AjK 0:564dd7a5d307 50 * @code
AjK 0:564dd7a5d307 51 * SimpleTask *task = new SimpleTask(100, func);
AjK 0:564dd7a5d307 52 * @endcode
AjK 0:564dd7a5d307 53 */
AjK 0:564dd7a5d307 54 class SimpleTask {
AjK 0:564dd7a5d307 55 public:
AjK 0:564dd7a5d307 56
AjK 0:564dd7a5d307 57 friend class SimpleScheduler;
AjK 0:564dd7a5d307 58
AjK 0:564dd7a5d307 59 void attach(void (*fptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 60 _callback->attach(fptr);
AjK 0:564dd7a5d307 61 }
AjK 0:564dd7a5d307 62
AjK 0:564dd7a5d307 63 template<typename T>
AjK 0:564dd7a5d307 64 void attach(T* tptr, void (T::*mptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 65 if((mptr != NULL) && (tptr != NULL)) {
AjK 0:564dd7a5d307 66 _callback->attach(tptr, mptr);
AjK 0:564dd7a5d307 67 }
AjK 0:564dd7a5d307 68 }
AjK 0:564dd7a5d307 69
AjK 0:564dd7a5d307 70 bool suspend(bool b) {
AjK 0:564dd7a5d307 71 bool prev = _suspended;
AjK 0:564dd7a5d307 72 _suspended = b;
AjK 0:564dd7a5d307 73 return prev;
AjK 0:564dd7a5d307 74 }
AjK 0:564dd7a5d307 75
AjK 0:564dd7a5d307 76 SimpleTask() { init(); }
AjK 0:564dd7a5d307 77
AjK 0:564dd7a5d307 78 // Constructor with frequency in miliseconds
AjK 0:564dd7a5d307 79 SimpleTask(int f) { init(f); }
AjK 0:564dd7a5d307 80
AjK 0:564dd7a5d307 81 // Constructor with frequency in miliseconds
AjK 0:564dd7a5d307 82 SimpleTask(double f) { init(1000.0 * f); }
AjK 0:564dd7a5d307 83
AjK 0:564dd7a5d307 84 // Constructor with frequency in miliseconds and function
AjK 0:564dd7a5d307 85 SimpleTask(int f, void (*fptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 86 init(f);
AjK 0:564dd7a5d307 87 _callback->attach(fptr);
AjK 0:564dd7a5d307 88 }
AjK 0:564dd7a5d307 89
AjK 0:564dd7a5d307 90 // Constructor with frequency in miliseconds and obj/method
AjK 0:564dd7a5d307 91 template<typename T>
AjK 0:564dd7a5d307 92 SimpleTask(int f, T* tptr, void (T::*mptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 93 init(f);
AjK 0:564dd7a5d307 94 if((mptr != NULL) && (tptr != NULL)) {
AjK 0:564dd7a5d307 95 _callback->attach(tptr, mptr);
AjK 0:564dd7a5d307 96 }
AjK 0:564dd7a5d307 97 }
AjK 0:564dd7a5d307 98
AjK 0:564dd7a5d307 99 // Constructor with frequency in miliseconds and function to call
AjK 0:564dd7a5d307 100 SimpleTask(double f, void (*fptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 101 init(f * 1000.0);
AjK 0:564dd7a5d307 102 _callback->attach(fptr);
AjK 0:564dd7a5d307 103 }
AjK 0:564dd7a5d307 104
AjK 0:564dd7a5d307 105 // Constructor with frequency in miliseconds and obj/method to call
AjK 0:564dd7a5d307 106 template<typename T>
AjK 0:564dd7a5d307 107 SimpleTask(double f, T* tptr, void (T::*mptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 108 init(f * 1000.0);
AjK 0:564dd7a5d307 109 if((mptr != NULL) && (tptr != NULL)) {
AjK 0:564dd7a5d307 110 _callback->attach(tptr, mptr);
AjK 0:564dd7a5d307 111 }
AjK 0:564dd7a5d307 112 }
AjK 0:564dd7a5d307 113
AjK 0:564dd7a5d307 114 ~SimpleTask() {
AjK 0:564dd7a5d307 115 delete(_callback);
AjK 0:564dd7a5d307 116 }
AjK 0:564dd7a5d307 117
AjK 0:564dd7a5d307 118 protected:
AjK 0:564dd7a5d307 119 STcallback *_callback;
AjK 0:564dd7a5d307 120 uint32_t _counter;
AjK 0:564dd7a5d307 121 uint32_t _reload;
AjK 0:564dd7a5d307 122 bool _suspended;
AjK 0:564dd7a5d307 123
AjK 0:564dd7a5d307 124 void init(int f = 0) {
AjK 0:564dd7a5d307 125 _counter = f;
AjK 0:564dd7a5d307 126 _reload = f;
AjK 0:564dd7a5d307 127 _suspended = false;
AjK 0:564dd7a5d307 128 _callback = new STcallback;
AjK 0:564dd7a5d307 129 }
AjK 0:564dd7a5d307 130 };
AjK 0:564dd7a5d307 131
AjK 0:564dd7a5d307 132 /** SimpleScheduler
AjK 0:564dd7a5d307 133 *
AjK 0:564dd7a5d307 134 * Manages a set of function or class.methods as tasks to
AjK 0:564dd7a5d307 135 * be called at a scheduled frquency. Simple round-robin
AjK 0:564dd7a5d307 136 * task caller. Note, it's cooperative. That means your
AjK 0:564dd7a5d307 137 * task functions must return BEFORE another task can be
AjK 0:564dd7a5d307 138 * called.
AjK 0:564dd7a5d307 139 *
AjK 0:564dd7a5d307 140 * @see http://mbed.org/cookbook/SimpleScheduler
AjK 0:564dd7a5d307 141 * @see example1.h
AjK 0:564dd7a5d307 142 * @see example2.h
AjK 0:564dd7a5d307 143 *
AjK 0:564dd7a5d307 144 * @code
AjK 0:564dd7a5d307 145 * #include "mbed.h"
AjK 0:564dd7a5d307 146 * #include "SimpleScheduler.h"
AjK 0:564dd7a5d307 147 *
AjK 0:564dd7a5d307 148 * DigitalOut led1(LED1);
AjK 0:564dd7a5d307 149 * DigitalOut led2(LED2);
AjK 0:564dd7a5d307 150 *
AjK 0:564dd7a5d307 151 * void f1(SimpleTask *task) { led1 = !led1; }
AjK 0:564dd7a5d307 152 * void f2(SimpleTask *task) { led2 = !led2; }
AjK 0:564dd7a5d307 153 *
AjK 0:564dd7a5d307 154 * SimpleScheduler *scheduler;
AjK 0:564dd7a5d307 155 *
AjK 0:564dd7a5d307 156 * int main() {
AjK 0:564dd7a5d307 157 *
AjK 0:564dd7a5d307 158 * scheduler = new SimpleScheduler;
AjK 0:564dd7a5d307 159 *
AjK 0:564dd7a5d307 160 * scheduler
AjK 0:564dd7a5d307 161 * ->addTask( new SimpleTask(0, f1) )
AjK 0:564dd7a5d307 162 * ->addTask( new SimpleTask(200, f2) )
AjK 0:564dd7a5d307 163 * ;
AjK 0:564dd7a5d307 164 *
AjK 0:564dd7a5d307 165 * scheduler->run();
AjK 0:564dd7a5d307 166 * }
AjK 0:564dd7a5d307 167 * @endcode
AjK 0:564dd7a5d307 168 */
AjK 0:564dd7a5d307 169 class SimpleScheduler {
AjK 0:564dd7a5d307 170 protected:
AjK 0:564dd7a5d307 171 Ticker _tick;
AjK 0:564dd7a5d307 172 list<SimpleTask *> _tasks;
AjK 0:564dd7a5d307 173 list<SimpleTask *>::iterator _itor;
AjK 0:564dd7a5d307 174
AjK 0:564dd7a5d307 175 friend class Ticker;
AjK 0:564dd7a5d307 176
AjK 0:564dd7a5d307 177 void ticktock(void) {
AjK 0:564dd7a5d307 178 for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) {
AjK 0:564dd7a5d307 179 if ((*itor)->_counter && !(*itor)->_suspended) {
AjK 0:564dd7a5d307 180 (*itor)->_counter--;
AjK 0:564dd7a5d307 181 }
AjK 0:564dd7a5d307 182 }
AjK 0:564dd7a5d307 183 }
AjK 0:564dd7a5d307 184
AjK 0:564dd7a5d307 185 public:
AjK 0:564dd7a5d307 186
AjK 0:564dd7a5d307 187 SimpleScheduler * addTask(SimpleTask *t) {
AjK 0:564dd7a5d307 188 _tasks.push_back(t);
AjK 0:564dd7a5d307 189 return this;
AjK 0:564dd7a5d307 190 }
AjK 0:564dd7a5d307 191
AjK 0:564dd7a5d307 192 void run(void) {
AjK 0:564dd7a5d307 193 _tick.attach_us(this, &SimpleScheduler::ticktock, 1000);
AjK 0:564dd7a5d307 194 while(1) {
AjK 0:564dd7a5d307 195 for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) {
AjK 0:564dd7a5d307 196 if((*itor)->_counter == 0) {
AjK 0:564dd7a5d307 197 (*itor)->_counter = (*itor)->_reload;
AjK 0:564dd7a5d307 198 if (!(*itor)->_suspended) {
AjK 0:564dd7a5d307 199 (*itor)->_callback->call();
AjK 0:564dd7a5d307 200 }
AjK 0:564dd7a5d307 201 }
AjK 0:564dd7a5d307 202 }
AjK 0:564dd7a5d307 203 }
AjK 0:564dd7a5d307 204 }
AjK 0:564dd7a5d307 205 };
AjK 0:564dd7a5d307 206
AjK 0:564dd7a5d307 207 }; // namespace AjK ends.
AjK 0:564dd7a5d307 208
AjK 0:564dd7a5d307 209 using namespace AjK;