aboutsummaryrefslogtreecommitdiff
path: root/src/TaskScheduler.cpp
diff options
context:
space:
mode:
authorAnatoli Arkhipenko <arkhipenko@hotmail.com>2015-10-15 23:33:31 -0400
committerAnatoli Arkhipenko <arkhipenko@hotmail.com>2015-10-15 23:37:01 -0400
commitbb20df9c654cbed77bb5007814ae06f20f08ec36 (patch)
tree0fe3b67dcfa7e070d10261d99cd0ec564ec3bf61 /src/TaskScheduler.cpp
parent07b0a9e49fd4c918821099aec940d0927c3f9ff5 (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.cpp323
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
-}
-
-