diff options
| author | Anatoli Arkhipenko <arkhipenko@hotmail.com> | 2015-10-15 23:33:31 -0400 |
|---|---|---|
| committer | Anatoli Arkhipenko <arkhipenko@hotmail.com> | 2015-10-15 23:37:01 -0400 |
| commit | bb20df9c654cbed77bb5007814ae06f20f08ec36 (patch) | |
| tree | 0fe3b67dcfa7e070d10261d99cd0ec564ec3bf61 /src/TaskScheduler.cpp | |
| parent | 07b0a9e49fd4c918821099aec940d0927c3f9ff5 (diff) | |
TaskScheduler version 1.8.0 - added support for event completion signallingv1.8.0
* Introduced option to compile with support for Status Rquests - ability to wait for and signal event completion
* Moved all code to one header file allowing control at compile time via #define statments.
Diffstat (limited to 'src/TaskScheduler.cpp')
| -rw-r--r-- | src/TaskScheduler.cpp | 323 |
1 files changed, 0 insertions, 323 deletions
diff --git a/src/TaskScheduler.cpp b/src/TaskScheduler.cpp deleted file mode 100644 index 5cdf2f4..0000000 --- a/src/TaskScheduler.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// Cooperative multitasking library for Arduino version 1.7.0 -// Copyright (c) 2015 Anatoli Arkhipenko -// - -/* ============================================ -Cooperative multitasking library code is placed under the MIT license -Copyright (c) 2015 Anatoli Arkhipenko - -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. -=============================================== -*/ - -#include "TaskScheduler.h" - -// ------------------ Task implementation -------------------- - -/** Constructor, uses default default values for the parameters - * so could be called with no parameters. - */ -Task::Task( unsigned long aInterval, long aIterations, void (*aCallback)(), Scheduler* aScheduler, bool aEnable, bool (*aOnEnable)(), void (*aOnDisable)() ) { - reset(); - set(aInterval, aIterations, aCallback); - setOnEnable(aOnEnable); - setOnDisable(aOnDisable); - if (aScheduler) aScheduler->addTask(*this); - if (aEnable) enable(); -} - -/** Resets (initializes) the task/ - * Task is not enabled and is taken out - * out of the execution chain as a result - */ -void Task::reset() { - iEnabled = false; - iPreviousMillis = 0; - iPrev = NULL; - iNext = NULL; - iScheduler = NULL; - iRunCounter = 0; -#ifdef _TASK_TIMECRITICAL - iOverrun = 0; -#endif -} - -/** Explicitly set Task execution parameters - * @param aInterval - execution interval in ms - * @param aIterations - number of iterations, use -1 for no limit - * @param aCallback - pointer to the callback function which executes the task actions - * @param aOnEnable - pointer to the callback function which is called on enable() - * @param aOnDisable - pointer to the callback function which is called on disable() - */ -void Task::set(unsigned long aInterval, long aIterations, void (*aCallback)(),bool (*aOnEnable)(), void (*aOnDisable)()) { - iInterval = aInterval; - iSetIterations = iIterations = aIterations; - iCallback = aCallback; - iOnEnable = aOnEnable; - iOnDisable = aOnDisable; -} - -/** Sets number of iterations for the task - * if task is enabled, schedule for immediate execution - * @param aIterations - number of iterations, use -1 for no limit - */ -void Task::setIterations(long aIterations) { - iSetIterations = iIterations = aIterations; -} - -/** Enables the task - * schedules it for execution as soon as possible, - * and resets the RunCounter back to zero - */ -void Task::enable() { - iEnabled = iOnEnable ? (*iOnEnable)() : true; - iRunCounter = 0; - iPreviousMillis = millis() - iInterval; -} - -/** Enables the task only if it was not enabled already - * Returns previous state (true if was already enabled, false if was not) - */ -bool Task::enableIfNot() { - bool previousEnabled = iEnabled; - if (!iEnabled) enable(); - return (previousEnabled); -} - -/** Enables the task - * and schedules it for execution after a delay = aInterval - */ -void Task::enableDelayed(unsigned long aDelay) { - enable(); - delay(aDelay); -} - -/** Delays Task for execution after a delay = aInterval (if task is enabled). - * leaves task enabled or disabled - * if aDelay is zero, delays for the original scheduling interval from now - */ -void Task::delay(unsigned long aDelay) { - if (!aDelay) aDelay = iInterval; - iPreviousMillis = millis() - iInterval + aDelay; -} - -/** Schedules next iteration of Task for execution immediately (if enabled) - * leaves task enabled or disabled - * Task's original schedule is shifted, and all subsequent iterations will continue from this point in time - */ -void Task::forceNextIteration() { - iPreviousMillis = millis() - iInterval; -} - -/** Sets the execution interval. - * Task execution is delayed for aInterval - * Use enable() to schedule execution ASAP - * @param aInterval - new execution interval - */ -void Task::setInterval (unsigned long aInterval) { - iInterval = aInterval; - delay(); -} - -/** Disables task - * Task will no longer be executed by the scheduler - * Returns status of the task before disable was called (i.e., if the task was already disabled) - */ -bool Task::disable() { - bool previousEnabled = iEnabled; - if (iEnabled && iOnDisable) (*iOnDisable)(); - iEnabled = false; - return (previousEnabled); -} - -/** Restarts task - * Task will run number of iterations again - */ -void Task::restart() { - iIterations = iSetIterations; - enable(); -} - -/** Restarts task delayed - * Task will run number of iterations again - */ -void Task::restartDelayed(unsigned long aDelay) { - iIterations = iSetIterations; - enableDelayed(aDelay); -} - -// ------------------ Scheduler implementation -------------------- - -/** Default constructor. - * Creates a scheduler with an empty execution chain. - */ -Scheduler::Scheduler() { - init(); -#ifdef _TASK_SLEEP_ON_IDLE_RUN - iAllowSleep = true; -#endif -} - -/** Appends task aTask to the tail of the execution chain. - * @param &aTask - reference to the Task to be appended. - * @note Task can only be part of the chain once. - */ - void Scheduler::addTask(Task& aTask) { - - aTask.iScheduler = this; -// First task situation: - if (iFirst == NULL) { - iFirst = &aTask; - aTask.iPrev = NULL; - } - else { -// This task gets linked back to the previous last one - aTask.iPrev = iLast; - iLast->iNext = &aTask; - } -// "Previous" last task gets linked to this one - as this one becomes the last one - aTask.iNext = NULL; - iLast = &aTask; -} - -/** Deletes specific Task from the execution chain - * @param &aTask - reference to the task to be deleted from the chain - */ -void Scheduler::deleteTask(Task& aTask) { - if (aTask.iPrev == NULL) { - if (aTask.iNext == NULL) { - iFirst = NULL; - iLast = NULL; - return; - } - else { - aTask.iNext->iPrev = NULL; - iFirst = aTask.iNext; - aTask.iNext = NULL; - return; - } - } - - if (aTask.iNext == NULL) { - aTask.iPrev->iNext = NULL; - iLast = aTask.iPrev; - aTask.iPrev = NULL; - return; - } - - aTask.iPrev->iNext = aTask.iNext; - aTask.iNext->iPrev = aTask.iPrev; - aTask.iPrev = NULL; - aTask.iNext = NULL; -} - -/** Disables all tasks in the execution chain - * Convenient for error situations, when the only - * task remaining active is an error processing task - */ -void Scheduler::disableAll() { - Task *current = iFirst; - while (current) { - current->disable(); - current = current->iNext; - } -} - - -/** Enables all the tasks in the execution chain - */ - void Scheduler::enableAll() { - Task *current = iFirst; - while (current) { - current->enable(); - current = current->iNext; - } -} - -/** Makes one pass through the execution chain. - * Tasks are executed in the order they were added to the chain - * There is no concept of priority - * Different pseudo "priority" could be achieved - * by running task more frequently - */ -void Scheduler::execute() { -#ifdef _TASK_SLEEP_ON_IDLE_RUN - bool idleRun = true; -#endif - - iCurrent = iFirst; - - while (iCurrent) { - do { - if (iCurrent->iEnabled) { - if (iCurrent->iIterations == 0) { - iCurrent->disable(); - break; - } - if (iCurrent->iInterval > 0) { - unsigned long targetMillis = iCurrent->iPreviousMillis + iCurrent->iInterval; - if (targetMillis <= millis()) { - if (iCurrent->iIterations > 0) iCurrent->iIterations--; // do not decrement (-1) being a signal of eternal task - iCurrent->iRunCounter++; - iCurrent->iPreviousMillis += iCurrent->iInterval; - - #ifdef _TASK_TIMECRITICAL - // Updated_previous+current should put us into the future, so iOverrun should be positive or zero. - // If negative - the task is behind (next execution time is already in the past) - iCurrent->iOverrun = (long) (iCurrent->iPreviousMillis + iCurrent->iInterval - millis()); - #endif - - if (iCurrent->iCallback) { - (*(iCurrent->iCallback))(); - #ifdef _TASK_SLEEP_ON_IDLE_RUN - idleRun = false; - #endif - } - break; - } - } - else { - if (iCurrent->iIterations > 0) iCurrent->iIterations--; // do not decrement (-1) being a signal of eternal task - iCurrent->iRunCounter++; - if (iCurrent->iCallback) { - (*(iCurrent->iCallback))(); - #ifdef _TASK_SLEEP_ON_IDLE_RUN - idleRun = false; - #endif - } - } - } - } while (0); //guaranteed single run - allows use of "break" to exit - iCurrent = iCurrent->iNext; - } - -#ifdef _TASK_SLEEP_ON_IDLE_RUN - if (idleRun && iAllowSleep) { - set_sleep_mode(SLEEP_MODE_IDLE); - sleep_enable(); - /* Now enter sleep mode. */ - sleep_mode(); - - /* The program will continue from here after the timer timeout ~1 ms */ - sleep_disable(); /* First thing to do is disable sleep. */ - } -#endif -} - - |
