Skip to content

API Task

Doanh Văn Lương edited this page Jan 24, 2018 · 32 revisions

TASKS


CREATION

  • Task()
Task();

Default constructor.
Takes no parameters and creates a task that could be scheduled to run at every scheduling pass indefinitely, but does not have a callback method defined, so no code execution will actually 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)())
  • Task(unsigned long aInterval, long aIterations, TaskCallback aCallback, Scheduler* aScheduler, bool aEnable, TaskOnEnable aOnEnable, TaskOnDisable aOnDisable)
Task(unsigned long aInterval, long aIterations, void (*aCallback)(), Scheduler* aScheduler, bool aEnable, bool (*aOnEnable)(), void (*aOnDisable)());
// OR
Task(unsigned long aInterval, long aIterations, TaskCallback aCallback, Scheduler* aScheduler, bool aEnable, TaskOnEnable aOnEnable, TaskOnDisable aOnDisable);

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)
  2. aIteration in number of times, -1 for indefinite execution (default = -1)
    Note: Tasks do not remember the number of iteration set initially. After the iterations are done, internal iteration counter is 0. If you need to perform another set of iterations, you need to set the number of iterations again.
    Note: Tasks which performed all their iterations remain active.
  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.

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()
  • unsigned long getInterval()
  • long getIterations()

The following 3 “getter” methods return task status (enabled/disabled), execution interval in milliseconds, number of remaining iterations.

bool isEnabled();
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.

CONTROL:

  • void enable()
void 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 which was enabled and requires execution.
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 the 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 to enable all tasks at the end of setup() method after all initializations are done.
If you require immediate execution of already enabled task, use forceNextIteratoin() 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 indefinte 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,...

  • void enableDelayed()
void enableDelayed();

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

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

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

  • void restart()
void 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.

  • void restartDelayed (unsigned long aDelay)
void 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).

  • 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 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 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 taks 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 not 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.

STATUS REQUEST METHODS:

  • void waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1)
  • void waitForDelayed(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1)
void waitFor(StatusRequest* aStatusRequest, unsigned long aInterval = 0, long aIterations = 1);
void 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)
  • 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.