Very simple cooperative round-robin task scheduler. See examples.
Diff: SimpleScheduler.h
- 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;