|
|
@@ -1,212 +1,216 @@
|
|
|
-// Cooperative multitasking library for Arduino
|
|
|
-// Copyright (c) 2015-2019 Anatoli Arkhipenko
|
|
|
-//
|
|
|
-// Changelog:
|
|
|
-// v1.0.0:
|
|
|
-// 2015-02-24 - Initial release
|
|
|
-// 2015-02-28 - added delay() and disableOnLastIteration() methods
|
|
|
-// 2015-03-25 - changed scheduler execute() method for a more precise delay calculation:
|
|
|
-// 1. Do not delay if any of the tasks ran (making request for immediate execution redundant)
|
|
|
-// 2. Delay is invoked only if none of the tasks ran
|
|
|
-// 3. Delay is based on the min anticipated wait until next task _AND_ the runtime of execute method itself.
|
|
|
-// 2015-05-11 - added restart() and restartDelayed() methods to restart tasks which are on hold after running all iterations
|
|
|
-// 2015-05-19 - completely removed delay from the scheduler since there are no power saving there. using 1 ms sleep instead
|
|
|
-//
|
|
|
-// v1.4.1:
|
|
|
-// 2015-09-15 - more careful placement of AVR-specific includes for sleep method (compatibility with DUE)
|
|
|
-// sleep on idle run is no longer a default and should be explicitly compiled with
|
|
|
-// _TASK_SLEEP_ON_IDLE_RUN defined
|
|
|
-//
|
|
|
-// v1.5.0:
|
|
|
-// 2015-09-20 - access to currently executing task (for callback methods)
|
|
|
-// 2015-09-20 - pass scheduler as a parameter to the task constructor to append the task to the end of the chain
|
|
|
-// 2015-09-20 - option to create a task already enabled
|
|
|
-//
|
|
|
-// v1.5.1:
|
|
|
-// 2015-09-21 - bug fix: incorrect handling of active tasks via set() and setIterations().
|
|
|
-// Thanks to Hannes Morgenstern for catching this one
|
|
|
-//
|
|
|
-// v1.6.0:
|
|
|
-// 2015-09-22 - revert back to having all tasks disable on last iteration.
|
|
|
-// 2015-09-22 - deprecated disableOnLastIteration method as a result
|
|
|
-// 2015-09-22 - created a separate branch 'disable-on-last-iteration' for this
|
|
|
-// 2015-10-01 - made version numbers semver compliant (documentation only)
|
|
|
-//
|
|
|
-// v1.7.0:
|
|
|
-// 2015-10-08 - introduced callback run counter - callback methods can branch on the iteration number.
|
|
|
-// 2015-10-11 - enableIfNot() - enable a task only if it is not already enabled. Returns true if was already enabled,
|
|
|
-// false if was disabled.
|
|
|
-// 2015-10-11 - disable() returns previous enable state (true if was enabled, false if was already disabled)
|
|
|
-// 2015-10-11 - introduced callback methods "on enable" and "on disable". On enable runs every time enable is called,
|
|
|
-// on disable runs only if task was enabled
|
|
|
-// 2015-10-12 - new Task method: forceNextIteration() - makes next iteration happen immediately during the next pass
|
|
|
-// regardless how much time is left
|
|
|
-//
|
|
|
-// v1.8.0:
|
|
|
-// 2015-10-13 - support for status request objects allowing tasks waiting on requests
|
|
|
-// 2015-10-13 - moved to a single header file to allow compilation control via #defines from the main sketch
|
|
|
-//
|
|
|
-// v1.8.1:
|
|
|
-// 2015-10-22 - implement Task id and control points to support identification of failure points for watchdog timer logging
|
|
|
-//
|
|
|
-// v1.8.2:
|
|
|
-// 2015-10-27 - implement Local Task Storage Pointer (allow use of same callback code for different tasks)
|
|
|
-// 2015-10-27 - bug: currentTask() method returns incorrect Task reference if called within OnEnable and OnDisable methods
|
|
|
-// 2015-10-27 - protection against infinite loop in OnEnable (if enable() methods are called within OnEnable)
|
|
|
-// 2015-10-29 - new currentLts() method in the scheduler class returns current task's LTS pointer in one call
|
|
|
-//
|
|
|
-// v1.8.3:
|
|
|
-// 2015-11-05 - support for task activation on a status request with arbitrary interval and number of iterations
|
|
|
-// (0 and 1 are still default values)
|
|
|
-// 2015-11-05 - implement waitForDelayed() method to allow task activation on the status request completion
|
|
|
-// delayed for one current interval
|
|
|
-// 2015-11-09 - added callback methods prototypes to all examples for Arduino IDE 1.6.6 compatibility
|
|
|
-// 2015-11-14 - added several constants to be used as task parameters for readability (e.g, TASK_FOREVER, TASK_SECOND, etc.)
|
|
|
-// 2015-11-14 - significant optimization of the scheduler's execute loop, including millis() rollover fix option
|
|
|
-//
|
|
|
-// v1.8.4:
|
|
|
-// 2015-11-15 - bug fix: Task alignment with millis() for scheduling purposes should be done after OnEnable, not before.
|
|
|
-// Especially since OnEnable method can change the interval
|
|
|
-// 2015-11-16 - further optimizations of the task scheduler execute loop
|
|
|
-//
|
|
|
-// v1.8.5:
|
|
|
-// 2015-11-23 - bug fix: incorrect calculation of next task invocation in case callback changed the interval
|
|
|
-// 2015-11-23 - bug fix: Task::set() method calls setInterval() explicitly, therefore delaying the task in the same manner
|
|
|
-//
|
|
|
-// v1.9.0:
|
|
|
-// 2015-11-24 - packed three byte-long status variables into bit array structure data type - saving 2 bytes per each task instance
|
|
|
-//
|
|
|
-// v1.9.2:
|
|
|
-// 2015-11-28 - _TASK_ROLLOVER_FIX is deprecated (not necessary)
|
|
|
-// 2015-12-16 - bug fixes: automatic millis rollover support for delay methods
|
|
|
-// 2015-12-17 - new method for _TASK_TIMECRITICAL option: getStartDelay()
|
|
|
-//
|
|
|
-// v2.0.0:
|
|
|
-// 2015-12-22 - _TASK_PRIORITY - support for layered task prioritization
|
|
|
-//
|
|
|
-// v2.0.1:
|
|
|
-// 2016-01-02 - bug fix: issue#11 Xtensa compiler (esp8266): Declaration of constructor does not match implementation
|
|
|
-//
|
|
|
-// v2.0.2:
|
|
|
-// 2016-01-05 - bug fix: time constants wrapped inside compile option
|
|
|
-// 2016-01-05 - support for ESP8266 wifi power saving mode for _TASK_SLEEP_ON_IDLE_RUN compile option
|
|
|
-//
|
|
|
-// v2.1.0:
|
|
|
-// 2016-02-01 - support for microsecond resolution
|
|
|
-// 2016-02-02 - added Scheduler baseline start time reset method: startNow()
|
|
|
-//
|
|
|
-// v2.2.0:
|
|
|
-// 2016-11-17 - all methods made 'inline' to support inclusion of TaskSchedule.h file into other header files
|
|
|
-//
|
|
|
-// v2.2.1:
|
|
|
-// 2016-11-30 - inlined constructors. Added "yield()" and "yieldOnce()" functions to easily break down and chain
|
|
|
-// back together long running callback methods
|
|
|
-// 2016-12-16 - added "getCount()" to StatusRequest objects, made every task StatusRequest enabled.
|
|
|
-// Internal StatusRequest objects are accessible via "getInternalStatusRequest()" method.
|
|
|
-//
|
|
|
-// v2.3.0:
|
|
|
-// 2017-02-24 - new timeUntilNextIteration() method within Scheduler class - inquire when a particlar task is
|
|
|
-// scheduled to run next time
|
|
|
-//
|
|
|
-// v2.4.0:
|
|
|
-// 2017-04-27 - added destructor to the Task class to ensure tasks are disables and taken off the execution chain
|
|
|
-// upon destruction. (Contributed by Edwin van Leeuwen [BlackEdder - https://github.com/BlackEdder)
|
|
|
-//
|
|
|
-// v2.5.0:
|
|
|
-// 2017-04-27 - ESP8266 ONLY: added optional support for std::functions via _TASK_STD_FUNCTION compilation option
|
|
|
-// (Contributed by Edwin van Leeuwen [BlackEdder - https://github.com/BlackEdder)
|
|
|
-// 2017-08-30 - add _TASK_DEBUG making all methods and variables public FOR DEBUGGING PURPOSES ONLY!
|
|
|
-// Use at your own risk!
|
|
|
-// 2017-08-30 - bug fix: Scheduler::addTask() checks if task is already part of an execution chain (github issue #37)
|
|
|
-// 2017-08-30 - support for multi-tab sketches (Contributed by Adam Ryczkowski - https://github.com/adamryczkowski)
|
|
|
-//
|
|
|
-// v2.5.1:
|
|
|
-// 2018-01-06 - support for IDLE sleep on Teensy boards (tested on Teensy 3.5)
|
|
|
-//
|
|
|
-// v2.5.2:
|
|
|
-// 2018-01-09 - _TASK_INLINE compilation directive making all methods declared "inline" (issue #42)
|
|
|
-//
|
|
|
-// v2.6.0:
|
|
|
-// 2018-01-30 - _TASK_TIMEOUT compilation directive: Task overall timeout functionality
|
|
|
-// 2018-01-30 - ESP32 support (experimental)
|
|
|
-// (Contributed by Marco Tombesi: https://github.com/baggior)
|
|
|
-//
|
|
|
-// v2.6.1:
|
|
|
-// 2018-02-13 - Bug: support for task self-destruction in the OnDisable method
|
|
|
-// Example 19: dynamic tasks creation and destruction
|
|
|
-// 2018-03-14 - Bug: high level scheduler ignored if lower level chain is empty
|
|
|
-// Example 20: use of local task storage to work with task-specific class objects
|
|
|
-//
|
|
|
-// v3.0.0:
|
|
|
-// 2018-03-15 - Major Release: Support for dynamic callback methods binding via compilation parameter _TASK_OO_CALLBACKS
|
|
|
-//
|
|
|
-// v3.0.1:
|
|
|
-// 2018-11-09 - bug: task deleted from the execution chain cannot be added back (github issue #67)
|
|
|
-//
|
|
|
-// v3.0.2:
|
|
|
-// 2018-11-11 - bug: default constructor is ambiguous when Status Request objects are enabled (github issue #65 & #68)
|
|
|
-//
|
|
|
-// v3.0.3:
|
|
|
-// 2019-06-13 - feature: custom sleep callback method: setSleepMethod() - ability to dynamically control idle sleep for various microcontrollers
|
|
|
-// - feature: support for MSP430 and MSP432 boards (pull request #75: big thanks to Guillaume Pirou, https://github.com/elominp)
|
|
|
-// - officially discontinued support for offile documentation in favor of updating the Wiki pages
|
|
|
-//
|
|
|
-// v3.1.0:
|
|
|
-// 2020-01-07 - feature: added 4 cpu load monitoring methods for _TASK_TIMECRITICAL compilation option
|
|
|
-//
|
|
|
-// v3.1.1:
|
|
|
-// 2020-01-09 - update: more precise CPU load measuring. Ability to define idle sleep threshold for ESP chips
|
|
|
-//
|
|
|
-// v3.1.2:
|
|
|
-// 2020-01-17 - bug fix: corrected external forward definitions of millis() and micros
|
|
|
-//
|
|
|
-// v3.1.3:
|
|
|
-// 2020-01-30 - bug fix: _TASK_DEFINE_MILLIS to force forward definition of millis and micros. Not defined by default.
|
|
|
-// 2020-02-16 - bug fix: add 'virtual' to the Task destructor definition (issue #86)
|
|
|
-//
|
|
|
-// v3.1.4:
|
|
|
-// 2020-02-22 - bug: get rid of unnecessary compiler warnings
|
|
|
-// 2020-02-22 - feature: access to the task chain with _TASK_EXPOSE_CHAIN compile option
|
|
|
-//
|
|
|
-// v3.1.5:
|
|
|
-// 2020-05-08 - feature: implemented light sleep for esp32
|
|
|
-//
|
|
|
-// v3.1.6:
|
|
|
-// 2020-05-12 - bug fix: deleteTask and addTask should check task ownership first (Issue #97)
|
|
|
-//
|
|
|
-// v3.1.7:
|
|
|
-// 2020-07-07 - warning fix: unused parameter 'aRecursive' (Issue #99)
|
|
|
-//
|
|
|
-// v3.2.0:
|
|
|
-// 2020-08-16 - feature: scheduling options
|
|
|
-//
|
|
|
-// v3.2.1:
|
|
|
-// 2020-10-04 - feature: Task.abort method. Stop task execution without calling OnDisable().
|
|
|
-//
|
|
|
-// v3.2.2:
|
|
|
-// 2020-12-14 - feature: enable and restart methods return true if task enabled
|
|
|
-// feature: Task.cancel() method - disable task with a cancel flag (could be used for alt. path
|
|
|
-// processing in the onDisable method.
|
|
|
-// feature: Task.cancelled() method - indicates that task was disabled with a cancel() method.
|
|
|
-//
|
|
|
-// v3.2.3:
|
|
|
-// 2021-01-01 - feature: discontinued use of 'register' keyword. Depricated in C++ 11
|
|
|
-// feature: add STM32 as a platform supporting _TASK_STD_FUNCTION. (PR #105)
|
|
|
-//
|
|
|
-// v3.3.0:
|
|
|
-// 2021-05-11 - feature: Timeout() methods for StatusRequest objects
|
|
|
-//
|
|
|
-// v3.4.0:
|
|
|
-// 2021-07-14 - feature: ability to Enable/Disable and Pause/Resume scheduling
|
|
|
-// - feature: optional use of external millis/micros methods
|
|
|
-//
|
|
|
-// v3.5.0:
|
|
|
-// 2021-11-01 - feature: adjust(long aInterval) method - adjust execution schedule:
|
|
|
-// + aInterval - shift schedule forward (later)
|
|
|
-// - aInterval - shift schedule backwards (earlier)
|
|
|
-//
|
|
|
-//
|
|
|
+/*
|
|
|
+Cooperative multitasking library for Arduino
|
|
|
+Copyright (c) 2015-2019 Anatoli Arkhipenko
|
|
|
+
|
|
|
+Changelog:
|
|
|
+v1.0.0:
|
|
|
+ 2015-02-24 - Initial release
|
|
|
+ 2015-02-28 - added delay() and disableOnLastIteration() methods
|
|
|
+ 2015-03-25 - changed scheduler execute() method for a more precise delay calculation:
|
|
|
+ 1. Do not delay if any of the tasks ran (making request for immediate execution redundant)
|
|
|
+ 2. Delay is invoked only if none of the tasks ran
|
|
|
+ 3. Delay is based on the min anticipated wait until next task _AND_ the runtime of execute method itself.
|
|
|
+ 2015-05-11 - added restart() and restartDelayed() methods to restart tasks which are on hold after running all iterations
|
|
|
+ 2015-05-19 - completely removed delay from the scheduler since there are no power saving there. using 1 ms sleep instead
|
|
|
+
|
|
|
+v1.4.1:
|
|
|
+ 2015-09-15 - more careful placement of AVR-specific includes for sleep method (compatibility with DUE)
|
|
|
+ sleep on idle run is no longer a default and should be explicitly compiled with
|
|
|
+ _TASK_SLEEP_ON_IDLE_RUN defined
|
|
|
+
|
|
|
+v1.5.0:
|
|
|
+ 2015-09-20 - access to currently executing task (for callback methods)
|
|
|
+ 2015-09-20 - pass scheduler as a parameter to the task constructor to append the task to the end of the chain
|
|
|
+ 2015-09-20 - option to create a task already enabled
|
|
|
+
|
|
|
+v1.5.1:
|
|
|
+ 2015-09-21 - bug fix: incorrect handling of active tasks via set() and setIterations().
|
|
|
+ Thanks to Hannes Morgenstern for catching this one
|
|
|
+
|
|
|
+v1.6.0:
|
|
|
+ 2015-09-22 - revert back to having all tasks disable on last iteration.
|
|
|
+ 2015-09-22 - deprecated disableOnLastIteration method as a result
|
|
|
+ 2015-09-22 - created a separate branch 'disable-on-last-iteration' for this
|
|
|
+ 2015-10-01 - made version numbers semver compliant (documentation only)
|
|
|
+
|
|
|
+v1.7.0:
|
|
|
+ 2015-10-08 - introduced callback run counter - callback methods can branch on the iteration number.
|
|
|
+ 2015-10-11 - enableIfNot() - enable a task only if it is not already enabled. Returns true if was already enabled,
|
|
|
+ false if was disabled.
|
|
|
+ 2015-10-11 - disable() returns previous enable state (true if was enabled, false if was already disabled)
|
|
|
+ 2015-10-11 - introduced callback methods "on enable" and "on disable". On enable runs every time enable is called,
|
|
|
+ on disable runs only if task was enabled
|
|
|
+ 2015-10-12 - new Task method: forceNextIteration() - makes next iteration happen immediately during the next pass
|
|
|
+ regardless how much time is left
|
|
|
+
|
|
|
+v1.8.0:
|
|
|
+ 2015-10-13 - support for status request objects allowing tasks waiting on requests
|
|
|
+ 2015-10-13 - moved to a single header file to allow compilation control via #defines from the main sketch
|
|
|
+
|
|
|
+v1.8.1:
|
|
|
+ 2015-10-22 - implement Task id and control points to support identification of failure points for watchdog timer logging
|
|
|
+
|
|
|
+v1.8.2:
|
|
|
+ 2015-10-27 - implement Local Task Storage Pointer (allow use of same callback code for different tasks)
|
|
|
+ 2015-10-27 - bug: currentTask() method returns incorrect Task reference if called within OnEnable and OnDisable methods
|
|
|
+ 2015-10-27 - protection against infinite loop in OnEnable (if enable() methods are called within OnEnable)
|
|
|
+ 2015-10-29 - new currentLts() method in the scheduler class returns current task's LTS pointer in one call
|
|
|
+
|
|
|
+v1.8.3:
|
|
|
+ 2015-11-05 - support for task activation on a status request with arbitrary interval and number of iterations
|
|
|
+ (0 and 1 are still default values)
|
|
|
+ 2015-11-05 - implement waitForDelayed() method to allow task activation on the status request completion
|
|
|
+ delayed for one current interval
|
|
|
+ 2015-11-09 - added callback methods prototypes to all examples for Arduino IDE 1.6.6 compatibility
|
|
|
+ 2015-11-14 - added several constants to be used as task parameters for readability (e.g, TASK_FOREVER, TASK_SECOND, etc.)
|
|
|
+ 2015-11-14 - significant optimization of the scheduler's execute loop, including millis() rollover fix option
|
|
|
+
|
|
|
+v1.8.4:
|
|
|
+ 2015-11-15 - bug fix: Task alignment with millis() for scheduling purposes should be done after OnEnable, not before.
|
|
|
+ Especially since OnEnable method can change the interval
|
|
|
+ 2015-11-16 - further optimizations of the task scheduler execute loop
|
|
|
+
|
|
|
+v1.8.5:
|
|
|
+ 2015-11-23 - bug fix: incorrect calculation of next task invocation in case callback changed the interval
|
|
|
+ 2015-11-23 - bug fix: Task::set() method calls setInterval() explicitly, therefore delaying the task in the same manner
|
|
|
+
|
|
|
+v1.9.0:
|
|
|
+ 2015-11-24 - packed three byte-long status variables into bit array structure data type - saving 2 bytes per each task instance
|
|
|
+
|
|
|
+v1.9.2:
|
|
|
+ 2015-11-28 - _TASK_ROLLOVER_FIX is deprecated (not necessary)
|
|
|
+ 2015-12-16 - bug fixes: automatic millis rollover support for delay methods
|
|
|
+ 2015-12-17 - new method for _TASK_TIMECRITICAL option: getStartDelay()
|
|
|
+
|
|
|
+v2.0.0:
|
|
|
+ 2015-12-22 - _TASK_PRIORITY - support for layered task prioritization
|
|
|
+
|
|
|
+v2.0.1:
|
|
|
+ 2016-01-02 - bug fix: issue#11 Xtensa compiler (esp8266): Declaration of constructor does not match implementation
|
|
|
+
|
|
|
+v2.0.2:
|
|
|
+ 2016-01-05 - bug fix: time constants wrapped inside compile option
|
|
|
+ 2016-01-05 - support for ESP8266 wifi power saving mode for _TASK_SLEEP_ON_IDLE_RUN compile option
|
|
|
+
|
|
|
+v2.1.0:
|
|
|
+ 2016-02-01 - support for microsecond resolution
|
|
|
+ 2016-02-02 - added Scheduler baseline start time reset method: startNow()
|
|
|
+
|
|
|
+v2.2.0:
|
|
|
+ 2016-11-17 - all methods made 'inline' to support inclusion of TaskSchedule.h file into other header files
|
|
|
+
|
|
|
+v2.2.1:
|
|
|
+ 2016-11-30 - inlined constructors. Added "yield()" and "yieldOnce()" functions to easily break down and chain
|
|
|
+ back together long running callback methods
|
|
|
+ 2016-12-16 - added "getCount()" to StatusRequest objects, made every task StatusRequest enabled.
|
|
|
+ Internal StatusRequest objects are accessible via "getInternalStatusRequest()" method.
|
|
|
+
|
|
|
+v2.3.0:
|
|
|
+ 2017-02-24 - new timeUntilNextIteration() method within Scheduler class - inquire when a particlar task is
|
|
|
+ scheduled to run next time
|
|
|
+
|
|
|
+v2.4.0:
|
|
|
+ 2017-04-27 - added destructor to the Task class to ensure tasks are disables and taken off the execution chain
|
|
|
+ upon destruction. (Contributed by Edwin van Leeuwen [BlackEdder - https://github.com/BlackEdder)
|
|
|
+
|
|
|
+v2.5.0:
|
|
|
+ 2017-04-27 - ESP8266 ONLY: added optional support for std::functions via _TASK_STD_FUNCTION compilation option
|
|
|
+ (Contributed by Edwin van Leeuwen [BlackEdder - https://github.com/BlackEdder)
|
|
|
+ 2017-08-30 - add _TASK_DEBUG making all methods and variables public FOR DEBUGGING PURPOSES ONLY!
|
|
|
+ Use at your own risk!
|
|
|
+ 2017-08-30 - bug fix: Scheduler::addTask() checks if task is already part of an execution chain (github issue #37)
|
|
|
+ 2017-08-30 - support for multi-tab sketches (Contributed by Adam Ryczkowski - https://github.com/adamryczkowski)
|
|
|
+
|
|
|
+v2.5.1:
|
|
|
+ 2018-01-06 - support for IDLE sleep on Teensy boards (tested on Teensy 3.5)
|
|
|
+
|
|
|
+v2.5.2:
|
|
|
+ 2018-01-09 - _TASK_INLINE compilation directive making all methods declared "inline" (issue #42)
|
|
|
+
|
|
|
+v2.6.0:
|
|
|
+ 2018-01-30 - _TASK_TIMEOUT compilation directive: Task overall timeout functionality
|
|
|
+ 2018-01-30 - ESP32 support (experimental)
|
|
|
+ (Contributed by Marco Tombesi: https://github.com/baggior)
|
|
|
+
|
|
|
+v2.6.1:
|
|
|
+ 2018-02-13 - Bug: support for task self-destruction in the OnDisable method
|
|
|
+ Example 19: dynamic tasks creation and destruction
|
|
|
+ 2018-03-14 - Bug: high level scheduler ignored if lower level chain is empty
|
|
|
+ Example 20: use of local task storage to work with task-specific class objects
|
|
|
+
|
|
|
+v3.0.0:
|
|
|
+ 2018-03-15 - Major Release: Support for dynamic callback methods binding via compilation parameter _TASK_OO_CALLBACKS
|
|
|
+
|
|
|
+v3.0.1:
|
|
|
+ 2018-11-09 - bug: task deleted from the execution chain cannot be added back (github issue #67)
|
|
|
+
|
|
|
+v3.0.2:
|
|
|
+ 2018-11-11 - bug: default constructor is ambiguous when Status Request objects are enabled (github issue #65 & #68)
|
|
|
+
|
|
|
+v3.0.3:
|
|
|
+ 2019-06-13 - feature: custom sleep callback method: setSleepMethod() - ability to dynamically control idle sleep for various microcontrollers
|
|
|
+ - feature: support for MSP430 and MSP432 boards (pull request #75: big thanks to Guillaume Pirou, https://github.com/elominp)
|
|
|
+ - officially discontinued support for offile documentation in favor of updating the Wiki pages
|
|
|
+
|
|
|
+v3.1.0:
|
|
|
+ 2020-01-07 - feature: added 4 cpu load monitoring methods for _TASK_TIMECRITICAL compilation option
|
|
|
+
|
|
|
+v3.1.1:
|
|
|
+ 2020-01-09 - update: more precise CPU load measuring. Ability to define idle sleep threshold for ESP chips
|
|
|
+
|
|
|
+v3.1.2:
|
|
|
+ 2020-01-17 - bug fix: corrected external forward definitions of millis() and micros
|
|
|
+
|
|
|
+v3.1.3:
|
|
|
+ 2020-01-30 - bug fix: _TASK_DEFINE_MILLIS to force forward definition of millis and micros. Not defined by default.
|
|
|
+ 2020-02-16 - bug fix: add 'virtual' to the Task destructor definition (issue #86)
|
|
|
+
|
|
|
+v3.1.4:
|
|
|
+ 2020-02-22 - bug: get rid of unnecessary compiler warnings
|
|
|
+ 2020-02-22 - feature: access to the task chain with _TASK_EXPOSE_CHAIN compile option
|
|
|
+
|
|
|
+v3.1.5:
|
|
|
+ 2020-05-08 - feature: implemented light sleep for esp32
|
|
|
+
|
|
|
+v3.1.6:
|
|
|
+ 2020-05-12 - bug fix: deleteTask and addTask should check task ownership first (Issue #97)
|
|
|
+
|
|
|
+v3.1.7:
|
|
|
+ 2020-07-07 - warning fix: unused parameter 'aRecursive' (Issue #99)
|
|
|
+
|
|
|
+v3.2.0:
|
|
|
+ 2020-08-16 - feature: scheduling options
|
|
|
+
|
|
|
+v3.2.1:
|
|
|
+ 2020-10-04 - feature: Task.abort method. Stop task execution without calling OnDisable().
|
|
|
+
|
|
|
+v3.2.2:
|
|
|
+ 2020-12-14 - feature: enable and restart methods return true if task enabled
|
|
|
+ feature: Task.cancel() method - disable task with a cancel flag (could be used for alt. path
|
|
|
+ processing in the onDisable method.
|
|
|
+ feature: Task.cancelled() method - indicates that task was disabled with a cancel() method.
|
|
|
+
|
|
|
+v3.2.3:
|
|
|
+ 2021-01-01 - feature: discontinued use of 'register' keyword. Depricated in C++ 11
|
|
|
+ feature: add STM32 as a platform supporting _TASK_STD_FUNCTION. (PR #105)
|
|
|
|
|
|
+v3.3.0:
|
|
|
+ 2021-05-11 - feature: Timeout() methods for StatusRequest objects
|
|
|
+
|
|
|
+v3.4.0:
|
|
|
+ 2021-07-14 - feature: ability to Enable/Disable and Pause/Resume scheduling
|
|
|
+ - feature: optional use of external millis/micros methods
|
|
|
+
|
|
|
+v3.5.0:
|
|
|
+ 2021-11-01 - feature: adjust(long aInterval) method - adjust execution schedule:
|
|
|
+ + aInterval - shift schedule forward (later)
|
|
|
+ - aInterval - shift schedule backwards (earlier)
|
|
|
+
|
|
|
+v3.6.0:
|
|
|
+ 2021-11-01 - feature: _TASK_THREAD_SAFE compile option for multi-core systems or running under RTOS
|
|
|
+
|
|
|
+
|
|
|
+*/
|
|
|
|
|
|
|
|
|
#include <Arduino.h>
|
|
|
@@ -243,6 +247,7 @@ extern "C" {
|
|
|
// #define _TASK_SCHEDULING_OPTIONS // Support for multiple scheduling options
|
|
|
// #define _TASK_DEFINE_MILLIS // Force forward declaration of millis() and micros() "C" style
|
|
|
// #define _TASK_EXTERNAL_TIME // Custom millis() and micros() methods
|
|
|
+// #define _TASK_THREAD_SAFE // Enable additional checking for thread safety
|
|
|
|
|
|
#ifdef _TASK_MICRO_RES
|
|
|
|
|
|
@@ -391,24 +396,48 @@ void StatusRequest::signalComplete(int aStatus) {
|
|
|
* If aStatusRequest is NULL, request for waiting is ignored, and the waiting task is not enabled.
|
|
|
*/
|
|
|
bool Task::waitFor(StatusRequest* aStatusRequest, unsigned long aInterval, long aIterations) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iStatusRequest = aStatusRequest;
|
|
|
if ( iStatusRequest != NULL ) { // assign internal StatusRequest var and check if it is not NULL
|
|
|
setIterations(aIterations);
|
|
|
setInterval(aInterval);
|
|
|
iStatus.waiting = _TASK_SR_NODELAY; // no delay
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
return enable();
|
|
|
}
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bool Task::waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval, long aIterations) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iStatusRequest = aStatusRequest;
|
|
|
if ( iStatusRequest != NULL ) { // assign internal StatusRequest var and check if it is not NULL
|
|
|
setIterations(aIterations);
|
|
|
if ( aInterval ) setInterval(aInterval); // For the dealyed version only set the interval if it was not a zero
|
|
|
iStatus.waiting = _TASK_SR_DELAY; // with delay equal to the current interval
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
return enable();
|
|
|
}
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -454,6 +483,11 @@ void Task::setOnDisable(TaskOnDisable aCallback) { iOnDisable = aCallback; }
|
|
|
* out of the execution chain as a result
|
|
|
*/
|
|
|
void Task::reset() {
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex = 1;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iStatus.enabled = false;
|
|
|
iStatus.inonenable = false;
|
|
|
iStatus.canceled = false;
|
|
|
@@ -492,6 +526,10 @@ void Task::reset() {
|
|
|
iStarttime = 0;
|
|
|
iStatus.timeout = false;
|
|
|
#endif // _TASK_TIMEOUT
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex = 0;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
/** Explicitly set Task execution parameters
|
|
|
@@ -506,13 +544,30 @@ void Task::reset() {
|
|
|
void Task::set(unsigned long aInterval, long aIterations) {
|
|
|
#else
|
|
|
void Task::set(unsigned long aInterval, long aIterations, TaskCallback aCallback, TaskOnEnable aOnEnable, TaskOnDisable aOnDisable) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iCallback = aCallback;
|
|
|
iOnEnable = aOnEnable;
|
|
|
iOnDisable = aOnDisable;
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
#endif // _TASK_OO_CALLBACKS
|
|
|
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
setInterval(aInterval);
|
|
|
iSetIterations = iIterations = aIterations;
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/** Sets number of iterations for the task
|
|
|
@@ -520,7 +575,15 @@ void Task::set(unsigned long aInterval, long aIterations, TaskCallback aCallback
|
|
|
* @param aIterations - number of iterations, use -1 for no limit
|
|
|
*/
|
|
|
void Task::setIterations(long aIterations) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iSetIterations = iIterations = aIterations;
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
#ifndef _TASK_OO_CALLBACKS
|
|
|
@@ -529,6 +592,10 @@ void Task::setIterations(long aIterations) {
|
|
|
* @param aCallback - pointer to the callback method for the next step
|
|
|
*/
|
|
|
void Task::yield (TaskCallback aCallback) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iCallback = aCallback;
|
|
|
forceNextIteration();
|
|
|
|
|
|
@@ -537,14 +604,26 @@ void Task::yield (TaskCallback aCallback) {
|
|
|
// a series of callback methods
|
|
|
iRunCounter--;
|
|
|
if ( iIterations >= 0 ) iIterations++;
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
/** Prepare task for next step iteration following yielding of control to the scheduler
|
|
|
* @param aCallback - pointer to the callback method for the next step
|
|
|
*/
|
|
|
void Task::yieldOnce (TaskCallback aCallback) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
yield(aCallback);
|
|
|
iIterations = 1;
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
#endif // _TASK_OO_CALLBACKS
|
|
|
|
|
|
@@ -555,6 +634,11 @@ void Task::yieldOnce (TaskCallback aCallback) {
|
|
|
*/
|
|
|
bool Task::enable() {
|
|
|
if (iScheduler) { // activation without active scheduler does not make sense
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iRunCounter = 0;
|
|
|
iStatus.canceled = false;
|
|
|
|
|
|
@@ -592,6 +676,11 @@ bool Task::enable() {
|
|
|
iMyStatusRequest.setWaiting();
|
|
|
#endif // _TASK_STATUS_REQUEST
|
|
|
}
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
return iStatus.enabled;
|
|
|
}
|
|
|
return false;
|
|
|
@@ -601,8 +690,17 @@ bool Task::enable() {
|
|
|
* Returns previous state (true if was already enabled, false if was not)
|
|
|
*/
|
|
|
bool Task::enableIfNot() {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
bool previousEnabled = iStatus.enabled;
|
|
|
if ( !previousEnabled ) enable();
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
return (previousEnabled);
|
|
|
}
|
|
|
|
|
|
@@ -610,20 +708,45 @@ bool Task::enableIfNot() {
|
|
|
* and schedules it for execution after a delay = aInterval
|
|
|
*/
|
|
|
bool Task::enableDelayed(unsigned long aDelay) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
enable();
|
|
|
delay(aDelay);
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
return iStatus.enabled;
|
|
|
}
|
|
|
|
|
|
#ifdef _TASK_TIMEOUT
|
|
|
void Task::setTimeout(unsigned long aTimeout, bool aReset) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iTimeout = aTimeout;
|
|
|
if (aReset) resetTimeout();
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
void Task::resetTimeout() {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iStarttime = _TASK_TIME_FUNCTION();
|
|
|
iStatus.timeout = false;
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
unsigned long Task::getTimeout() {
|
|
|
@@ -650,14 +773,27 @@ bool Task::timedOut() {
|
|
|
* if aDelay is zero, delays for the original scheduling interval from now
|
|
|
*/
|
|
|
void Task::delay(unsigned long aDelay) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iDelay = aDelay ? aDelay : iInterval;
|
|
|
iPreviousMillis = _TASK_TIME_FUNCTION();
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
/** Adjusts Task execution with aInterval (if task is enabled).
|
|
|
*/
|
|
|
void Task::adjust(long aInterval) {
|
|
|
if ( aInterval == 0 ) return; // nothing to do for a zero
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
if ( aInterval < 0 ) {
|
|
|
iPreviousMillis += aInterval;
|
|
|
}
|
|
|
@@ -665,6 +801,9 @@ void Task::adjust(long aInterval) {
|
|
|
iDelay += aInterval; // we have to adjust delay because adjusting iPreviousMillis might push
|
|
|
// it into the future beyond current millis() and cause premature trigger
|
|
|
}
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -673,7 +812,15 @@ void Task::adjust(long aInterval) {
|
|
|
* Task's original schedule is shifted, and all subsequent iterations will continue from this point in time
|
|
|
*/
|
|
|
void Task::forceNextIteration() {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iPreviousMillis = _TASK_TIME_FUNCTION() - (iDelay = iInterval);
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
/** Sets the execution interval.
|
|
|
@@ -682,8 +829,16 @@ void Task::forceNextIteration() {
|
|
|
* @param aInterval - new execution interval
|
|
|
*/
|
|
|
void Task::setInterval (unsigned long aInterval) {
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex++;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
iInterval = aInterval;
|
|
|
delay(); // iDelay will be updated by the delay() function
|
|
|
+
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ iMutex--;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
}
|
|
|
|
|
|
/** Disables task
|
|
|
@@ -807,12 +962,13 @@ Scheduler::~Scheduler() {
|
|
|
/** Initializes all internal varaibles
|
|
|
*/
|
|
|
void Scheduler::init() {
|
|
|
+ iEnabled = false;
|
|
|
+
|
|
|
iFirst = NULL;
|
|
|
iLast = NULL;
|
|
|
iCurrent = NULL;
|
|
|
|
|
|
iPaused = false;
|
|
|
- iEnabled = true;
|
|
|
|
|
|
#ifdef _TASK_PRIORITY
|
|
|
iHighPriority = NULL;
|
|
|
@@ -825,6 +981,8 @@ void Scheduler::init() {
|
|
|
#ifdef _TASK_TIMECRITICAL
|
|
|
cpuLoadReset();
|
|
|
#endif // _TASK_TIMECRITICAL
|
|
|
+
|
|
|
+ iEnabled = true;
|
|
|
}
|
|
|
|
|
|
/** Appends task aTask to the tail of the execution chain.
|
|
|
@@ -832,12 +990,13 @@ void Scheduler::init() {
|
|
|
* @note Task can only be part of the chain once.
|
|
|
*/
|
|
|
void Scheduler::addTask(Task& aTask) {
|
|
|
-
|
|
|
// If task already belongs to a scheduler, we should not be adding
|
|
|
// it to this scheduler. It should be deleted from the other scheduler first.
|
|
|
if (aTask.iScheduler != NULL)
|
|
|
return;
|
|
|
|
|
|
+ iEnabled = false;
|
|
|
+
|
|
|
aTask.iScheduler = this;
|
|
|
// First task situation:
|
|
|
if (iFirst == NULL) {
|
|
|
@@ -852,6 +1011,8 @@ void Scheduler::init() {
|
|
|
// "Previous" last task gets linked to this one - as this one becomes the last one
|
|
|
aTask.iNext = NULL;
|
|
|
iLast = &aTask;
|
|
|
+
|
|
|
+ iEnabled = true;
|
|
|
}
|
|
|
|
|
|
/** Deletes specific Task from the execution chain
|
|
|
@@ -862,17 +1023,21 @@ void Scheduler::deleteTask(Task& aTask) {
|
|
|
if (aTask.iScheduler != this)
|
|
|
return;
|
|
|
|
|
|
+ iEnabled = false;
|
|
|
+
|
|
|
aTask.iScheduler = NULL;
|
|
|
if (aTask.iPrev == NULL) {
|
|
|
if (aTask.iNext == NULL) {
|
|
|
iFirst = NULL;
|
|
|
iLast = NULL;
|
|
|
+ iEnabled = true;
|
|
|
return;
|
|
|
}
|
|
|
else {
|
|
|
aTask.iNext->iPrev = NULL;
|
|
|
iFirst = aTask.iNext;
|
|
|
aTask.iNext = NULL;
|
|
|
+ iEnabled = true;
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
@@ -881,6 +1046,7 @@ void Scheduler::deleteTask(Task& aTask) {
|
|
|
aTask.iPrev->iNext = NULL;
|
|
|
iLast = aTask.iPrev;
|
|
|
aTask.iPrev = NULL;
|
|
|
+ iEnabled = true;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -888,6 +1054,8 @@ void Scheduler::deleteTask(Task& aTask) {
|
|
|
aTask.iNext->iPrev = aTask.iPrev;
|
|
|
aTask.iPrev = NULL;
|
|
|
aTask.iNext = NULL;
|
|
|
+
|
|
|
+ iEnabled = true;
|
|
|
}
|
|
|
|
|
|
/** Disables all tasks in the execution chain
|
|
|
@@ -900,6 +1068,9 @@ void Scheduler::disableAll(bool aRecursive) {
|
|
|
#else
|
|
|
void Scheduler::disableAll() {
|
|
|
#endif
|
|
|
+
|
|
|
+ iEnabled = false;
|
|
|
+
|
|
|
Task *current = iFirst;
|
|
|
while (current) {
|
|
|
current->disable();
|
|
|
@@ -909,6 +1080,8 @@ void Scheduler::disableAll() {
|
|
|
#ifdef _TASK_PRIORITY
|
|
|
if (aRecursive && iHighPriority) iHighPriority->disableAll(true);
|
|
|
#endif // _TASK_PRIORITY
|
|
|
+
|
|
|
+ iEnabled = true;
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -920,6 +1093,9 @@ void Scheduler::enableAll(bool aRecursive) {
|
|
|
#else
|
|
|
void Scheduler::enableAll() {
|
|
|
#endif
|
|
|
+
|
|
|
+ iEnabled = false;
|
|
|
+
|
|
|
Task *current = iFirst;
|
|
|
while (current) {
|
|
|
current->enable();
|
|
|
@@ -930,6 +1106,7 @@ void Scheduler::enableAll() {
|
|
|
if (aRecursive && iHighPriority) iHighPriority->enableAll(true);
|
|
|
#endif // _TASK_PRIORITY
|
|
|
|
|
|
+ iEnabled = true;
|
|
|
}
|
|
|
|
|
|
/** Sets scheduler for the higher priority tasks (support for layered task priority)
|
|
|
@@ -963,6 +1140,8 @@ void Scheduler::startNow() {
|
|
|
#endif
|
|
|
unsigned long t = _TASK_TIME_FUNCTION();
|
|
|
|
|
|
+ iEnabled = false;
|
|
|
+
|
|
|
iCurrent = iFirst;
|
|
|
while (iCurrent) {
|
|
|
if ( iCurrent->iStatus.enabled ) iCurrent->iPreviousMillis = t - iCurrent->iDelay;
|
|
|
@@ -972,6 +1151,8 @@ void Scheduler::startNow() {
|
|
|
#ifdef _TASK_PRIORITY
|
|
|
if (aRecursive && iHighPriority) iHighPriority->startNow( true );
|
|
|
#endif // _TASK_PRIORITY
|
|
|
+
|
|
|
+ iEnabled = true;
|
|
|
}
|
|
|
|
|
|
/** Returns number millis or micros until next scheduled iteration of a given task
|
|
|
@@ -1067,7 +1248,7 @@ bool Scheduler::execute() {
|
|
|
iCurrentScheduler = this;
|
|
|
#endif // _TASK_PRIORITY
|
|
|
|
|
|
- // each scheduled is enabled/disabled individually, so check iEnabed only
|
|
|
+ // each scheduled is enabled/disabled individually, so check iEnabled only
|
|
|
// after the higher priority scheduler has been invoked.
|
|
|
if ( !iEnabled ) return true; // consider this to be an idle run
|
|
|
|
|
|
@@ -1087,6 +1268,12 @@ bool Scheduler::execute() {
|
|
|
do {
|
|
|
if ( iCurrent->iStatus.enabled ) {
|
|
|
|
|
|
+#ifdef _TASK_THREAD_SAFE
|
|
|
+ // this task is in the scheduling state and should not be invoked
|
|
|
+ // as there could be incosistent settings until scheduling is done
|
|
|
+ if ( iCurrent->iMutex ) break;
|
|
|
+#endif // _TASK_THREAD_SAFE
|
|
|
+
|
|
|
#ifdef _TASK_WDT_IDS
|
|
|
// For each task the control points are initialized to avoid confusion because of carry-over:
|
|
|
iCurrent->iControlPoint = 0;
|