Very simple cooperative round-robin task scheduler. See examples.
SimpleScheduler.h
- Committer:
- pkunnals
- Date:
- 2021-04-15
- Revision:
- 5:1dfc64077059
- Parent:
- 3:95ec5c83c2fe
File content as of revision 5:1dfc64077059:
/* Copyright (c) 2011 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 */ #ifndef AJK_SIMPLESCHEDULER_H #define AJK_SIMPLESCHEDULER_H #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 example3.h * @see example4.h * @see http://mbed.org/cookbook/SimpleScheduler * * @code * SimpleTask *task = new SimpleTask(100); * task->attach(func); * @endcode * @code * SimpleTask *task = new SimpleTask(100, func); // Every 100ms * SimpleTask *task = new SimpleTask(1.0, func); // Every 1second * @endcode * * When creating new SimpleTasks you pass the time as a frequency * of how often to call the task function. If the time is an integer * then milliseconds is assumed. If the number you pass is a read (double) * number then the time assumed is seconds. */ 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; } // 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); * DigitalOut led3(LED3); * * void f1(SimpleTask *task) { led1 = !led1; } * void f2(SimpleTask *task) { led2 = !led2; } * void f3(SimpleTask *task) { led3 = !led3; } * * SimpleScheduler *scheduler; * * int main() { * * scheduler = new SimpleScheduler; * * scheduler * ->addTask( new SimpleTask(0, f1) ) // As often as possible * ->addTask( new SimpleTask(200, f2) ) // Every 200milliseconds * ->addTask( new SimpleTask(1.0, f3) ) // Once a second * ; * * 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((*itor)); } } } } } }; }; // namespace AjK ends. using namespace AjK; #endif