Very simple cooperative round-robin task scheduler. See examples.
Embed:
(wiki syntax)
Show/hide line numbers
SimpleScheduler.h
00001 /* 00002 Copyright (c) 2011 Andy Kirkham 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 00022 @file SimpleScheduler.h 00023 @purpose Simple round-robin cooperative scheduler 00024 @version see ChangeLog.c 00025 @date Mar 2011 00026 @author Andy Kirkham 00027 */ 00028 00029 #ifndef AJK_SIMPLESCHEDULER_H 00030 #define AJK_SIMPLESCHEDULER_H 00031 00032 #include "mbed.h" 00033 #include <list> 00034 #include "STcallback.h" 00035 00036 namespace AjK { 00037 00038 /** SimpleTask 00039 * 00040 * A defined function task requires a "holder" for SimpleScheduler 00041 * to manage it. This is the holder class. 00042 * 00043 * @see SimpleScheduler 00044 * @see example1.h 00045 * @see example2.h 00046 * @see example3.h 00047 * @see example4.h 00048 * @see http://mbed.org/cookbook/SimpleScheduler 00049 * 00050 * @code 00051 * SimpleTask *task = new SimpleTask(100); 00052 * task->attach(func); 00053 * @endcode 00054 * @code 00055 * SimpleTask *task = new SimpleTask(100, func); // Every 100ms 00056 * SimpleTask *task = new SimpleTask(1.0, func); // Every 1second 00057 * @endcode 00058 * 00059 * When creating new SimpleTasks you pass the time as a frequency 00060 * of how often to call the task function. If the time is an integer 00061 * then milliseconds is assumed. If the number you pass is a read (double) 00062 * number then the time assumed is seconds. 00063 */ 00064 class SimpleTask { 00065 public: 00066 00067 friend class SimpleScheduler; 00068 00069 void attach(void (*fptr)(SimpleTask *pST)) { 00070 _callback->attach(fptr); 00071 } 00072 00073 template<typename T> 00074 void attach(T* tptr, void (T::*mptr)(SimpleTask *pST)) { 00075 if((mptr != NULL) && (tptr != NULL)) { 00076 _callback->attach(tptr, mptr); 00077 } 00078 } 00079 00080 bool suspend(bool b) { 00081 bool prev = _suspended; 00082 _suspended = b; 00083 return prev; 00084 } 00085 00086 // Constructor with frequency in miliseconds 00087 SimpleTask(int f) { init(f); } 00088 00089 // Constructor with frequency in miliseconds 00090 SimpleTask(double f) { init(1000.0 * f); } 00091 00092 // Constructor with frequency in miliseconds and function 00093 SimpleTask(int f, void (*fptr)(SimpleTask *pST)) { 00094 init(f); 00095 _callback->attach(fptr); 00096 } 00097 00098 // Constructor with frequency in miliseconds and obj/method 00099 template<typename T> 00100 SimpleTask(int f, T* tptr, void (T::*mptr)(SimpleTask *pST)) { 00101 init(f); 00102 if((mptr != NULL) && (tptr != NULL)) { 00103 _callback->attach(tptr, mptr); 00104 } 00105 } 00106 00107 // Constructor with frequency in miliseconds and function to call 00108 SimpleTask(double f, void (*fptr)(SimpleTask *pST)) { 00109 init(f * 1000.0); 00110 _callback->attach(fptr); 00111 } 00112 00113 // Constructor with frequency in miliseconds and obj/method to call 00114 template<typename T> 00115 SimpleTask(double f, T* tptr, void (T::*mptr)(SimpleTask *pST)) { 00116 init(f * 1000.0); 00117 if((mptr != NULL) && (tptr != NULL)) { 00118 _callback->attach(tptr, mptr); 00119 } 00120 } 00121 00122 ~SimpleTask() { 00123 delete(_callback); 00124 } 00125 00126 protected: 00127 STcallback *_callback; 00128 uint32_t _counter; 00129 uint32_t _reload; 00130 bool _suspended; 00131 00132 void init(int f = 0) { 00133 _counter = f; 00134 _reload = f; 00135 _suspended = false; 00136 _callback = new STcallback; 00137 } 00138 }; 00139 00140 /** SimpleScheduler 00141 * 00142 * Manages a set of function or class.methods as tasks to 00143 * be called at a scheduled frquency. Simple round-robin 00144 * task caller. Note, it's cooperative. That means your 00145 * task functions must return BEFORE another task can be 00146 * called. 00147 * 00148 * @see http://mbed.org/cookbook/SimpleScheduler 00149 * @see example1.h 00150 * @see example2.h 00151 * 00152 * @code 00153 * #include "mbed.h" 00154 * #include "SimpleScheduler.h" 00155 * 00156 * DigitalOut led1(LED1); 00157 * DigitalOut led2(LED2); 00158 * DigitalOut led3(LED3); 00159 * 00160 * void f1(SimpleTask *task) { led1 = !led1; } 00161 * void f2(SimpleTask *task) { led2 = !led2; } 00162 * void f3(SimpleTask *task) { led3 = !led3; } 00163 * 00164 * SimpleScheduler *scheduler; 00165 * 00166 * int main() { 00167 * 00168 * scheduler = new SimpleScheduler; 00169 * 00170 * scheduler 00171 * ->addTask( new SimpleTask(0, f1) ) // As often as possible 00172 * ->addTask( new SimpleTask(200, f2) ) // Every 200milliseconds 00173 * ->addTask( new SimpleTask(1.0, f3) ) // Once a second 00174 * ; 00175 * 00176 * scheduler->run(); 00177 * } 00178 * @endcode 00179 */ 00180 class SimpleScheduler { 00181 protected: 00182 Ticker _tick; 00183 list<SimpleTask *> _tasks; 00184 list<SimpleTask *>::iterator _itor; 00185 00186 friend class Ticker; 00187 00188 void ticktock(void) { 00189 for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) { 00190 if ((*itor)->_counter && !(*itor)->_suspended) { 00191 (*itor)->_counter--; 00192 } 00193 } 00194 } 00195 00196 public: 00197 00198 SimpleScheduler * addTask(SimpleTask *t) { 00199 _tasks.push_back(t); 00200 return this; 00201 } 00202 00203 void run(void) { 00204 _tick.attach_us(this, &SimpleScheduler::ticktock, 1000); 00205 while(1) { 00206 for (list<SimpleTask *>::iterator itor = _tasks.begin(); itor != _tasks.end(); ++itor) { 00207 if((*itor)->_counter == 0) { 00208 (*itor)->_counter = (*itor)->_reload; 00209 if (!(*itor)->_suspended) { 00210 (*itor)->_callback->call((*itor)); 00211 } 00212 } 00213 } 00214 } 00215 } 00216 }; 00217 00218 }; // namespace AjK ends. 00219 00220 using namespace AjK; 00221 00222 #endif
Generated on Fri Jul 15 2022 08:21:53 by 1.7.2