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

Dependents:   Garage_Control

Committer:
AjK
Date:
Fri Mar 04 13:10:39 2011 +0000
Revision:
3:95ec5c83c2fe
Parent:
2:974a420997a9
1.2 See ChangeLog.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:564dd7a5d307 1 /*
AjK 1:f043501c4bed 2 Copyright (c) 2011 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 3:95ec5c83c2fe 29 #ifndef AJK_SIMPLESCHEDULER_H
AjK 3:95ec5c83c2fe 30 #define AJK_SIMPLESCHEDULER_H
AjK 0:564dd7a5d307 31
AjK 0:564dd7a5d307 32 #include "mbed.h"
AjK 0:564dd7a5d307 33 #include <list>
AjK 0:564dd7a5d307 34 #include "STcallback.h"
AjK 0:564dd7a5d307 35
AjK 0:564dd7a5d307 36 namespace AjK {
AjK 0:564dd7a5d307 37
AjK 0:564dd7a5d307 38 /** SimpleTask
AjK 0:564dd7a5d307 39 *
AjK 0:564dd7a5d307 40 * A defined function task requires a "holder" for SimpleScheduler
AjK 0:564dd7a5d307 41 * to manage it. This is the holder class.
AjK 0:564dd7a5d307 42 *
AjK 0:564dd7a5d307 43 * @see SimpleScheduler
AjK 0:564dd7a5d307 44 * @see example1.h
AjK 0:564dd7a5d307 45 * @see example2.h
AjK 3:95ec5c83c2fe 46 * @see example3.h
AjK 3:95ec5c83c2fe 47 * @see example4.h
AjK 0:564dd7a5d307 48 * @see http://mbed.org/cookbook/SimpleScheduler
AjK 0:564dd7a5d307 49 *
AjK 0:564dd7a5d307 50 * @code
AjK 0:564dd7a5d307 51 * SimpleTask *task = new SimpleTask(100);
AjK 0:564dd7a5d307 52 * task->attach(func);
AjK 0:564dd7a5d307 53 * @endcode
AjK 0:564dd7a5d307 54 * @code
AjK 3:95ec5c83c2fe 55 * SimpleTask *task = new SimpleTask(100, func); // Every 100ms
AjK 3:95ec5c83c2fe 56 * SimpleTask *task = new SimpleTask(1.0, func); // Every 1second
AjK 0:564dd7a5d307 57 * @endcode
AjK 3:95ec5c83c2fe 58 *
AjK 3:95ec5c83c2fe 59 * When creating new SimpleTasks you pass the time as a frequency
AjK 3:95ec5c83c2fe 60 * of how often to call the task function. If the time is an integer
AjK 3:95ec5c83c2fe 61 * then milliseconds is assumed. If the number you pass is a read (double)
AjK 3:95ec5c83c2fe 62 * number then the time assumed is seconds.
AjK 0:564dd7a5d307 63 */
AjK 0:564dd7a5d307 64 class SimpleTask {
AjK 0:564dd7a5d307 65 public:
AjK 0:564dd7a5d307 66
AjK 0:564dd7a5d307 67 friend class SimpleScheduler;
AjK 0:564dd7a5d307 68
AjK 0:564dd7a5d307 69 void attach(void (*fptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 70 _callback->attach(fptr);
AjK 0:564dd7a5d307 71 }
AjK 0:564dd7a5d307 72
AjK 0:564dd7a5d307 73 template<typename T>
AjK 0:564dd7a5d307 74 void attach(T* tptr, void (T::*mptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 75 if((mptr != NULL) && (tptr != NULL)) {
AjK 0:564dd7a5d307 76 _callback->attach(tptr, mptr);
AjK 0:564dd7a5d307 77 }
AjK 0:564dd7a5d307 78 }
AjK 0:564dd7a5d307 79
AjK 0:564dd7a5d307 80 bool suspend(bool b) {
AjK 0:564dd7a5d307 81 bool prev = _suspended;
AjK 0:564dd7a5d307 82 _suspended = b;
AjK 0:564dd7a5d307 83 return prev;
AjK 0:564dd7a5d307 84 }
AjK 0:564dd7a5d307 85
AjK 0:564dd7a5d307 86 // Constructor with frequency in miliseconds
AjK 0:564dd7a5d307 87 SimpleTask(int f) { init(f); }
AjK 0:564dd7a5d307 88
AjK 0:564dd7a5d307 89 // Constructor with frequency in miliseconds
AjK 0:564dd7a5d307 90 SimpleTask(double f) { init(1000.0 * f); }
AjK 0:564dd7a5d307 91
AjK 0:564dd7a5d307 92 // Constructor with frequency in miliseconds and function
AjK 0:564dd7a5d307 93 SimpleTask(int f, void (*fptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 94 init(f);
AjK 0:564dd7a5d307 95 _callback->attach(fptr);
AjK 0:564dd7a5d307 96 }
AjK 0:564dd7a5d307 97
AjK 0:564dd7a5d307 98 // Constructor with frequency in miliseconds and obj/method
AjK 0:564dd7a5d307 99 template<typename T>
AjK 0:564dd7a5d307 100 SimpleTask(int f, T* tptr, void (T::*mptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 101 init(f);
AjK 0:564dd7a5d307 102 if((mptr != NULL) && (tptr != NULL)) {
AjK 0:564dd7a5d307 103 _callback->attach(tptr, mptr);
AjK 0:564dd7a5d307 104 }
AjK 0:564dd7a5d307 105 }
AjK 0:564dd7a5d307 106
AjK 0:564dd7a5d307 107 // Constructor with frequency in miliseconds and function to call
AjK 0:564dd7a5d307 108 SimpleTask(double f, void (*fptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 109 init(f * 1000.0);
AjK 0:564dd7a5d307 110 _callback->attach(fptr);
AjK 0:564dd7a5d307 111 }
AjK 0:564dd7a5d307 112
AjK 0:564dd7a5d307 113 // Constructor with frequency in miliseconds and obj/method to call
AjK 0:564dd7a5d307 114 template<typename T>
AjK 0:564dd7a5d307 115 SimpleTask(double f, T* tptr, void (T::*mptr)(SimpleTask *pST)) {
AjK 0:564dd7a5d307 116 init(f * 1000.0);
AjK 0:564dd7a5d307 117 if((mptr != NULL) && (tptr != NULL)) {
AjK 0:564dd7a5d307 118 _callback->attach(tptr, mptr);
AjK 0:564dd7a5d307 119 }
AjK 0:564dd7a5d307 120 }
AjK 0:564dd7a5d307 121
AjK 0:564dd7a5d307 122 ~SimpleTask() {
AjK 0:564dd7a5d307 123 delete(_callback);
AjK 0:564dd7a5d307 124 }
AjK 0:564dd7a5d307 125
AjK 0:564dd7a5d307 126 protected:
AjK 0:564dd7a5d307 127 STcallback *_callback;
AjK 0:564dd7a5d307 128 uint32_t _counter;
AjK 0:564dd7a5d307 129 uint32_t _reload;
AjK 0:564dd7a5d307 130 bool _suspended;
AjK 0:564dd7a5d307 131
AjK 0:564dd7a5d307 132 void init(int f = 0) {
AjK 0:564dd7a5d307 133 _counter = f;
AjK 0:564dd7a5d307 134 _reload = f;
AjK 0:564dd7a5d307 135 _suspended = false;
AjK 0:564dd7a5d307 136 _callback = new STcallback;
AjK 0:564dd7a5d307 137 }
AjK 0:564dd7a5d307 138 };
AjK 0:564dd7a5d307 139
AjK 0:564dd7a5d307 140 /** SimpleScheduler
AjK 0:564dd7a5d307 141 *
AjK 0:564dd7a5d307 142 * Manages a set of function or class.methods as tasks to
AjK 0:564dd7a5d307 143 * be called at a scheduled frquency. Simple round-robin
AjK 0:564dd7a5d307 144 * task caller. Note, it's cooperative. That means your
AjK 0:564dd7a5d307 145 * task functions must return BEFORE another task can be
AjK 0:564dd7a5d307 146 * called.
AjK 0:564dd7a5d307 147 *
AjK 0:564dd7a5d307 148 * @see http://mbed.org/cookbook/SimpleScheduler
AjK 0:564dd7a5d307 149 * @see example1.h
AjK 0:564dd7a5d307 150 * @see example2.h
AjK 0:564dd7a5d307 151 *
AjK 0:564dd7a5d307 152 * @code
AjK 0:564dd7a5d307 153 * #include "mbed.h"
AjK 0:564dd7a5d307 154 * #include "SimpleScheduler.h"
AjK 0:564dd7a5d307 155 *
AjK 0:564dd7a5d307 156 * DigitalOut led1(LED1);
AjK 0:564dd7a5d307 157 * DigitalOut led2(LED2);
AjK 3:95ec5c83c2fe 158 * DigitalOut led3(LED3);
AjK 0:564dd7a5d307 159 *
AjK 0:564dd7a5d307 160 * void f1(SimpleTask *task) { led1 = !led1; }
AjK 0:564dd7a5d307 161 * void f2(SimpleTask *task) { led2 = !led2; }
AjK 3:95ec5c83c2fe 162 * void f3(SimpleTask *task) { led3 = !led3; }
AjK 0:564dd7a5d307 163 *
AjK 0:564dd7a5d307 164 * SimpleScheduler *scheduler;
AjK 0:564dd7a5d307 165 *
AjK 0:564dd7a5d307 166 * int main() {
AjK 0:564dd7a5d307 167 *
AjK 0:564dd7a5d307 168 * scheduler = new SimpleScheduler;
AjK 0:564dd7a5d307 169 *
AjK 0:564dd7a5d307 170 * scheduler
AjK 3:95ec5c83c2fe 171 * ->addTask( new SimpleTask(0, f1) ) // As often as possible
AjK 3:95ec5c83c2fe 172 * ->addTask( new SimpleTask(200, f2) ) // Every 200milliseconds
AjK 3:95ec5c83c2fe 173 * ->addTask( new SimpleTask(1.0, f3) ) // Once a second
AjK 0:564dd7a5d307 174 * ;
AjK 0:564dd7a5d307 175 *
AjK 0:564dd7a5d307 176 * scheduler->run();
AjK 0:564dd7a5d307 177 * }
AjK 0:564dd7a5d307 178 * @endcode
AjK 0:564dd7a5d307 179 */
AjK 0:564dd7a5d307 180 class SimpleScheduler {
AjK 0:564dd7a5d307 181 protected:
AjK 0:564dd7a5d307 182 Ticker _tick;
AjK 0:564dd7a5d307 183 list<SimpleTask *> _tasks;
AjK 0:564dd7a5d307 184 list<SimpleTask *>::iterator _itor;
AjK 0:564dd7a5d307 185
AjK 0:564dd7a5d307 186 friend class Ticker;
AjK 0:564dd7a5d307 187
AjK 0:564dd7a5d307 188 void ticktock(void) {
AjK 0:564dd7a5d307 189 for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) {
AjK 0:564dd7a5d307 190 if ((*itor)->_counter && !(*itor)->_suspended) {
AjK 0:564dd7a5d307 191 (*itor)->_counter--;
AjK 0:564dd7a5d307 192 }
AjK 0:564dd7a5d307 193 }
AjK 0:564dd7a5d307 194 }
AjK 0:564dd7a5d307 195
AjK 0:564dd7a5d307 196 public:
AjK 0:564dd7a5d307 197
AjK 0:564dd7a5d307 198 SimpleScheduler * addTask(SimpleTask *t) {
AjK 0:564dd7a5d307 199 _tasks.push_back(t);
AjK 0:564dd7a5d307 200 return this;
AjK 0:564dd7a5d307 201 }
AjK 0:564dd7a5d307 202
AjK 0:564dd7a5d307 203 void run(void) {
AjK 0:564dd7a5d307 204 _tick.attach_us(this, &SimpleScheduler::ticktock, 1000);
AjK 0:564dd7a5d307 205 while(1) {
AjK 0:564dd7a5d307 206 for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) {
AjK 0:564dd7a5d307 207 if((*itor)->_counter == 0) {
AjK 0:564dd7a5d307 208 (*itor)->_counter = (*itor)->_reload;
AjK 0:564dd7a5d307 209 if (!(*itor)->_suspended) {
AjK 2:974a420997a9 210 (*itor)->_callback->call((*itor));
AjK 0:564dd7a5d307 211 }
AjK 0:564dd7a5d307 212 }
AjK 0:564dd7a5d307 213 }
AjK 0:564dd7a5d307 214 }
AjK 0:564dd7a5d307 215 }
AjK 0:564dd7a5d307 216 };
AjK 0:564dd7a5d307 217
AjK 0:564dd7a5d307 218 }; // namespace AjK ends.
AjK 0:564dd7a5d307 219
AjK 0:564dd7a5d307 220 using namespace AjK;
AjK 3:95ec5c83c2fe 221
AjK 3:95ec5c83c2fe 222 #endif