Skip to content

API Task

Anatoli Arkhipenko edited this page Oct 10, 2022 · 32 revisions

TASKS


CREATION

  • Task()
Task();

Default constructor.
Takes no parameters and creates a task that needs to be scheduled to run explicitly. There is no callback method defined, and the number of iterations is set to zero by default, so no code execution will take place.
All tasks are created disabled by default.

  • Task(unsigned long aInterval, long aIterations, void (aCallback)(), Scheduler aScheduler, bool aEnable, bool (*aOnEnable)(), void (*aOnDisable)(), bool aSelfdestruct)
  • Task(unsigned long aInterval, long aIterations, TaskCallback aCallback, Scheduler* aScheduler, bool aEnable, TaskOnEnable aOnEnable, TaskOnDisable aOnDisable, bool aSelfdestruct)
Task(unsigned long aInterval, long aIterations, void (*aCallback)(), Scheduler* aScheduler, bool aEnable, bool (*aOnEnable)(), void (*aOnDisable)(), bool aSelfdestruct);
// OR
Task(unsigned long aInterval, long aIterations, TaskCallback aCallback, Scheduler* aScheduler, bool aEnable, TaskOnEnable aOnEnable, TaskOnDisable aOnDisable, bool aSelfdestruct);

Constructor with parameters.
Creates a task that is scheduled to run every <aInterval> milliseconds, <aIterations> times, executing <aCallback> method on every pass.

  1. aInterval is in milliseconds (or microseconds) (default = 0 or TASK_IMMEDIATE)
  2. aIteration in number of times, -1 or TASK_FOREVER for indefinite execution (default = 0)
    Note: Tasks remember the number of iteration set initially, and could be restarted. After the iterations are done, the internal iteration counter is 0. If you need to perform a different set of iterations, you need to set the number of iterations explicitly.
    Note: Tasks which performed all their iterations will be disabled during next scheduling run.
  3. aCallback is a pointer to a void callback method without parameters (default = NULL)
  4. aScheduler – optional reference to existing scheduler. If supplied (not NULL) this task will be appended to the task chain of the current scheduler). (default = NULL)
  5. aEnable – optional. Value of true will create task enabled. (default = false)
  6. aOnEnable is a pointer to a bool callback method without parameters, invoked when task is enabled. If OnEnable method returns true, task is enabled. If OnEnable method return false, task remains disabled (default = NULL)
  7. aOnDisable is a pointer to a void callback method without parameters, invoked when task is disabled (default = NULL)
    All tasks are created disabled by default (unless aEnable = true). You have to explicitly enable the task for execution.
  8. Enables/disables self-destruct on disable event. (default = false). Only if compiled with _TASK_SELF_DESTRUCT option.

NOTE: OnEnable callback method is called immediately when task is enabled, which could be well ahead of the scheduled execution time of the task. Please bear that in mind – other tasks, hardware, serial interface may not even be initialized yet. It is always advisable to explicitly enable tasks with OnEnable methods after all initialization methods completed (e.g., at the end of setup() method)
Enabled task is scheduled for execution as soon as the Scheduler's execute() methods gets control. In order to delay first run of the task, use enableDelayed or delay method (for enabled tasks) method.

  • Task(void (aCallback)(), Scheduler aScheduler, bool (*aOnEnable)(), void (*aOnDisable)())
Task(void (*aCallback)(), Scheduler* aScheduler, bool (*aOnEnable)(), void (*aOnDisable)());

If compiled with support for Status Request objects, this constructor creates a Task for activation on event (since such tasks must run waitFor() method, their interval, iteration and enabled status will be set by that method (to 0, 1 and false respectively).

INFORMATION

  • bool isEnabled()
  • bool canceled()
  • unsigned long getInterval()
  • long getIterations()

The following 4 “getter” methods return task status (enabled/disabled), cancled flag (in case Task execution was canceled or aborted), execution interval in milliseconds, number of remaining iterations.

bool isEnabled();
bool canceled();
unsigned long getInterval();
long getIterations();
  • long getStartDelay()
long getStartDelay();

If library is compiled with _TASK_TIMECRITICAL enabled, you can assess how much later the callback method was invoked against when it was scheduled to be invoked. The return value of getStartDelay() method provides this information in milliseconds (or microseconds).

  • long getOverrun()
long getOverrun();

If library is compiled with _TASK_TIMECRITICAL enabled, tasks are monitored for “long running” scenario. A “long running” task is a task that does not finish processing its callback methods quickly, and thus creates a situation for itself and other tasks where they don't run on a scheduled interval, but rather “catch up” and are behind. When task scheduler sets the next execution target time, it adds Task's execution interval to the previously scheduled execution time:

next execution time = current execution scheduled time + task execution interval

If next execution time happens to be already in the past (next execution time < millis()), then task is considered overrun. GetOverrun method returns number of milliseconds between next execution time and current time. If the value is negative, the task has overrun (cut into the) next execution interval by that many milliseconds.
Positive value indicate number of milliseconds (or microseconds) of slack this task has for execution purposes.

  • unsigned long getRunCounter()
unsigned long getRunCounter();

Returns the number of the current run. “Current run” is the number of times a callback method has been invoked since the last time a task was enabled.
NOTE: The runCounter value is incremented before callback method is invoked. If a task is checking the runCounter value within its callback method, then the first run value is 1. If task T1 is checking the runCounter value of another task (T2) , then value = 0 indicates that T2 has not been invoked yet, and value = 1 indicates that T2 has run once.

  • bool isFirstIteration()
bool isFirstIteration();

Indicates whether current pass is (or will be) a first iteration of the task.

  • bool isLastIteration()
bool isLastIteration();

For tasks with a limited number of iterations only, indicates whether current pass is the last iteration.

  • Task* getPreviousTask()
Task*  getPreviousTask();

If compiled with _TASK_EXPOSE_CHAIN option returns pointer to the Task previous to this one in the scheduler execution chain.

  • Task* getNextTask()
Task*  getNextTask();

If compiled with _TASK_EXPOSE_CHAIN option returns a pointer to the Task next after this one in the scheduler execution chain. This does not mean that the Task will be invoked next however, it only means that it will be evaluated for invocation next by the scheduler.

CONTROL:

  • bool enable()
bool enable();

Enables the task, and schedules it for immediate execution (without delay) at this or next scheduling pass depending on when the task was enabled. Scheduler will execute the next pass without any delay because there is a task that was enabled and requires execution.

Returns: true if task was enabled, and false otherwise

NOTE: if task being enabled is not assigned to a scheduler and is not part of execution chain, then task will not be enabled.

NOTE: enable() invokes task’s OnEnable method (if not NULL) immediately, which can prepare task for execution. OnEnable must return a value of true for task to be enabled. If OnEnable returns false, task remains disabled. OnEnable is invoked every time enable is called, regardless if task is already enabled or not. Alignment to current millis() is performed after OnEnable exits, so any changes to the interval inside OnEnable is taken into consideration.
TaskScheduler allows tasks to be added to a Scheduler and enabled at the time of creation. Be very careful with such tasks – the OnEnable method will be executed immediately, while certain objects (i.e., other Tasks, libraries) are not yet ready (e.g., Wire.begin() was not yet called), or hardware not yet activated (pins not set to INPUT or OUTPUT).
It is very much recommended to enable all tasks at the end of setup() method after all initializations are done.
If you require immediate execution of the already enabled task, use forceNextIteration() method instead of enable(): it achieves the result, but does not call OnEnable method.

NOTE: in the event enable() method is called inside the OnEnable callback method (thus basically creating an infinite loop), TaskScheduler will only call OnEnable once (thus protecting the Task against OnEnable infinite loop).

NOTE: internal StatusRequest object will be set waiting for an event when Task is enabled (if TaskScheduler is compiled with support for StatusRequests). StatusRequest object is set waiting after the call to onEnable() method of the Task (if defined). Consequently, any Task#2 that is expected to wait on this Task’s internal StatusRequest should do it only after this task is enabled.

  • bool enableIfNot()
bool enableIfNot();

Enables the task only if it was previously disabled.

Returns previous enable state: true if task was already enabled, and false if task was disabled.

Since enable() schedules Task for execution immediately, this method provides a way to activate tasks and schedule them for immediate execution only if they are not active already.

All NOTES from the enable() method apply.

  • void delay()
void delay();

Schedules the task for execution after a delay (aInterval), but does not change the enabled/disabled status of the task.
NOTE: a delay of 0 (zero) will delay task for current execution interval. Use **forceNextIteration()** method to force execution of the task’s callback during immediate next scheduling pass.

  • void forceNextIteration()
void forceNextIteration();

Schedules the task for execution during immediate next scheduling pass.
The Task must be already enabled prior to this method.
Note: Task’s schedule is adjusted to run from this moment in time. For instance: if a task was running every 10 seconds: 10, 20, 30, .., calling forceNextIteration at 44th second of task execution will make subsequent schedule look like: 44, 54, 64, 74,...

  • bool enableDelayed()
bool enableDelayed();

Enables the task, and schedules it for execution after task's current scheduling interval (aInterval).

Returns: true if task was enabled, and false otherwise

  • bool enableDelayed (unsigned long aDelay)
bool enableDelayed (unsigned long aDelay);

Enables the task, and schedules it for execution after a specific delay (aDelay, which may be different from aInterval).

Returns: true if task was enabled, and false otherwise

  • bool restart()
bool restart();

For tasks with limited number of iterations only, restart method will re-enable the task, set the number of iterations back to last set value, and schedule task for execution as soon as possible.

Returns: true if task was enabled, and false otherwise

  • bool restartDelayed (unsigned long aDelay)
bool restartDelayed (unsigned long aDelay);

Same as restart() method, with the only difference being that Task is scheduled to run first iteration after a delay = aDelay milliseconds (or microseconds).

Returns: true if task was enabled, and false otherwise

  • bool disable()
bool disable();

Disables the task. Scheduler will not execute this task any longer, even if it remains in the chain. Task can be later re-enabled for execution.
Return previous enabled state: true if task was enabled prior to calling disable, and false otherwise.
If not NULL, task’s OnDisable method is invoked immediately. OnDisable is invoked only if task was in enabled state. Calling disable 3 times for instance will invoke OnDisable only once.

NOTE: internal StatusRequest object will signal completion of an event when Task is disabled (if TaskScheduler is compiled with support for StatusRequests). StatusRequest object is set complete after the call to onDisable() method of the Task (if defined). Consequently, the task which has to signal its completion to other Tasks could not restart itself. Do so will not ever set the internal StatusRequest object to a complete status, since the Task is never really disabled.

  • void cancel()
void cancel();

Disables the task and sets canceled flag. Similarly to disable() method cancel() will call OnDisable() method (if provided), where the canceled flag could be examined and appropriate action taken.

  • void abort()
void abort();

Similar to the cancel() - aborts task execution, however without calling OnDisable() method. The Task is just not scheduled for execution anymore. StatusRequest objects are not triggered.

  • void set(unsigned long aInterval, long aIterations, void (*aCallback)() , bool (*aOnEnable)() , void (*aOnDisable)())
void set(unsigned long aInterval, long aIterations, void (*aCallback)() , bool (*aOnEnable)() , void (*aOnDisable)());

Allows dynamic control of task execution parameters in one method call.
NOTE: OnEnable and OnDisable parameters can be omitted. In that case they will be assigned to NULL and respective methods will no longer be called. Therefore it is advisable to use either all five parameters explicitly, or employ individual “setter” methods below instead.

  • void setSelfDestruct(bool aSelfDestruct=true)
void void setSelfDestruct(bool aSelfDestruct=true);

If compiled with _TASK_SELF_DESTRUCT option, requests Task to be deleted after disable() method is invoked (if aSelfDestruct == true) or not to be deleted (if aSelfDestruct == false)

  • bool getSelfDestruct()
void bool getSelfDestruct();

If compiled with _TASK_SELF_DESTRUCT option, returns current state of the self-destruct request (true: self-destruct on disable(), false: keep task after disable())

NOTE Default behavior is not to delete task after disable() is invoked.

  • void setInterval (unsigned long aInterval)
  • void setIterations (long aIterations)
  • void setCallback (void (*aCallback)())
  • void setOnEnable (bool (*aCallback)())
  • void setOnDisable (void (*aCallback)())

Next five “setter” methods allow changes of individual task execution control parameters.

void setInterval (unsigned long aInterval);
void setIterations (long aIterations);
void setCallback (void (*aCallback)());
void setOnEnable (bool (*aCallback)());
void setOnDisable (void (*aCallback)());

NOTE: Next execution time calculation takes place after the callback method is called, so new interval will be used immediately by the scheduler. For the situations when one task is changing the interval parameter for the other, setInterval method calls delay explicitly to guarantee schedule change, however it does not enable the task if task is disabled.
NOTE: Tasks that ran through all their allocated iterations are disabled. SetIterations() method DOES NOT enable the task. Either enable explicitly, or use restart methods.
Please note that as a result execution of the tasks is delayed by the provided interval. If immediate invocation is required, call forceNextIteration() method after setting a new interval.

  • void yield(void (*aCallback)())
void yield(void (*aCallback)());

This method could be used to break up long callback methods. A long callback method should be broken up into several shorter methods. Yield method just gives control back to scheduler, while ensuring that next iteration of the Task is executed immediately with the next callback method. Basically yield(&callBack2) is equivalent to setting new callback method, and forcing next iteration to be immediate. Please note that original interval and number of iterations are preserved. Even the runcounter of the callback2 after yielding will remain the same. Typically a call to yield() method is the last line of the method yielding.

  • void yieldOnce(void (*aCallback)())
void yieldOnce(void (*aCallback)());

This method is equivalent to yield(), only execution of the target aСallback method is set to happen only once, after which the Task will be disabled.

TIMEOUT METHODS:

NOTE ON TIMEOUT: Timeout conditions are evaluated first. Which means that a task that is ready to be disabled due to last iteration and a timeout, will be disabled with a timeout flag set. This is by design. To make timeout a secondary choice, you need to use a separate “timeout” task and place it after this task in the execution chain.

Once set, a timeout value remains with the task, i.e., when a disabled task is restarted or reenabled, the timeout will restart as well. To disable timeout, use setTimeout(TASK_NOTIMEOUT); method call.

  • void setTimeout(unsigned long aTimeout, bool aReset=false)
void setTimeout(unsigned long aTimeout, bool aReset=false)

Sets the task’s timeout to the aTimeout milliseconds (microseconds) value. Setting timeout to TASK_NOTIMEOUT value will disable the timeout. If aReset is false or not supplied, the timeout counter is not activated for the task If aReset is true, the current value of millis() [or micros()] is set as a starting point in time. NOTE: Tasks’ timeout starting points are reset automatically by enable(), enableDelayed(), enableIfNot(), restart() and restartDelayed() methods.

  • void resetTimeout()
void resetTimeout();

Resets Task’s timeout start value to current time. Effectively the timeout countdown restarts from the beginning. NOTE: enable(), enableDelayed(), enableIfNot(), restart() and restartDelayed() methods call resetTimeout() explicitly. There is no need to reset timeouts for the tasks that have been just enabled or restarted.

  • unsigned long getTimeout()
unsigned long getTimeout();

Returns Task’s initial timeout value. A value of TASK_NOTIMEOUT (0) indicates that this task has not timeout set.

  • long untilTimeout()
long untilTimeout();

Returns amount of time remaining until this task will time out. NOTE: Take care using this method: it returns a **signed **integer, with a negative value meaning the task has already or is about to timeout: -1 = the task has already timed outstanding value < -1 = the task is still active but will time out at next iteration.

  • bool timedOut()
bool timedOut();

Returns true if the task was disabled due to a timeout. Returns false if a timeout has not occurred (either not yet, or the task deactivated under normal conditions – ran out of iterations). NOTE: Best place to use this method is in the OnDisable method of a task to determine how termination has occurred. Please see example 17 for details.

STATUS REQUEST METHODS:

  • bool waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1)
  • bool waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1)
bool waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
bool waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);

If compiled with support for Status Requests, these methods make task wait for the completion of aStatusRequest event. By default waitFor() sets tasks interval to 0 (zero) for immediate execution when event happens, and also sets the number of iterations to 1. However, you can specify different interval and number of iterations.
By default waitForDelayed() sets tasks interval to a supplied value or (if omitted or zero) keeps the current interval, so delayed execution will take place when the event happens. It also sets the number of iterations to 1 by default if not supplied.
When Status Request object completes, all tasks waiting on it are executed during next scheduling pass. Tasks waiting via waitFor() method are executed immediately. Tasks waiting via waitForDelayed() method are activated, but executed after current or supplied interval delay. NOTE: aStatusRequest should be “activated” by calling setWaiting() method before making a task wait on it. Otherwise, the task will execute immediately.
The sequence of events to use Status Request object is as follows:

  1. Create a status request object
  2. Activate status request object (calling its setWaiting() method)
  3. Set up tasks to wait of the event completion
  4. Signal completion of event(s)

Returns: true if task was enabled, false otherwise.

  • StatusRequest* getStatusRequest()
StatusRequest* getStatusRequest();

Returns a pointer to StatusReqeust object this Task was waiting on.

  • StatusRequest* getInternalStatusRequest()
StatusRequest* getInternalStatusRequest();

Returns a pointer to an internal StatusReqeust object associated with this Task. Internal StatusRequest object is:

  1. Always waits on 1 event – completion of this task
  2. Is activated (set to “waiting” status) after Task is enabled
  3. Is completed after Task is disabled (either explicitly, or by running out of iterations)

NOTE: Please remember that a task is deactivated at the next scheduling pass after the last iteration, which means that other Tasks in the chain will have a chance to run before Task StatusRequest signaling completion of the internal StatusRequest. However, there is no further delay – deactivation will take place at the next scheduling pass.

TASK ID, CONTROL POINTS METHODS:

  • void setId(unsigned int aID)
void setId(unsigned int aID);

If compiled with support for Task IDs, this method will set the task ID explicitly. Calling this method is not necessary as task IDs are assigned automatically during task creation: 1, 2, 3,…

  • unsigned int getId()
unsigned int getId();

If compiled with support for Task IDs, this method return current task’s ID.

  • void setControlPoint (unsigned int aPoint)
void setControlPoint (unsigned int aPoint);

If compiled with support for Task IDs, this method will set a control point in the task’s code.
Control points are similar to “try…catch” blocks, with control point ID specifying where in the code the “try” part started, and a mechanism like watchdog timer providing the “catch” functionality.

  • unsigned int getControlPoint()
unsigned int getControlPoint();

If compiled with support for Task IDs, this method will return currently set control point for this task.

LOCAL TASK STORAGE METHODS:

  • void setLtsPointer(void *aPtr)
void setLtsPointer(void *aPtr);

If compiled with support for LTS, this method will set the task's local storage pointer.

  • void *getLtsPointer()
void *getLtsPointer();

If compiled with support for LTS, this method will return reference to the task's local storage.
NOTE: the value returned has type (void *), and needs to be re-cast into appropriate pointer type. Please refer to example sketches for implementation options.

Clone this wiki locally