-
Notifications
You must be signed in to change notification settings - Fork 243
API Task Scheduler
- Scheduler()
- void init()
- void addTask(Task& aTask)
- void deleteTask(Task& aTask)
- void allowSleep(bool aState)
- void setSleepMethod(SleepCallback aCallback)
- void enableAll(bool aRecursive = true)
- void disableAll(bool aRecursive = true)
- Task& currentTask()
- void* currentLts()
- void startNow (bool aRecursive = true)
- long timeUntilNextIteration (Task& aTask)
- bool execute()
- bool isOverrun()
Scheduler();
Default constructor. Takes no parameters. Creates task scheduler with default parameters and an empty task queue.
void init();
Initializes the task queue and scheduler parameters, Executed as part of constructor, so don't need to be explicitly called after creation.
Note: be default (if compiled with _TASK_TIMECRITICAL
enabled) scheduler is allowed to put processor to IDLE sleep mode. If this behavior was changed via allowSleep()
method, inti()
will NOT reset allow sleep particular parameter.
void addTask(Task& aTask);
Adds task aTask
to the execution queue (or chain) of tasks by appending it to the end of the chain. If two tasks are scheduled for execution, the sequence will match the order in which tasks were appended to the chain. However, in reality, due to different timing of task execution, the actual order may be different.
Note: Currently, changing the execution sequence in a chain dynamically is not supported.
If you need to reorder the chain sequence – initialize the scheduler and re-add the tasks in a different order.
void deleteTask(Task& aTask);
Deletes task aTask
from the execution chain. The chain of remaining tasks is linked together (i.e if original task chain is 1 → 2 → 3 → 4
, deleting 3
will result in 1 → 2 → 4
).
Note: it is not required to delete a task from the chain. A disabled task will not be executed anyway, but you save a few microseconds per scheduling pass by deleting it, since it is not even considered for execution.
An example of proper use of this method would be running some sort of initialize
task in the chain, and then deleting it from the chain since it only needs to run once.
void allowSleep(bool aState);
Available in the API only if compiled with _TASK_SLEEP_ON_IDLE_RUN
enabled.
Controls whether scheduler is allowed (aState = true
), or not (aState = false
) to put processor into IDLE sleep mode in case not tasks are scheduled to run.
The default
behavior of scheduler upon creation is to allow sleep mode.
void setSleepMethod(SleepCallback aCallback);
Available in the API only if compiled with _TASK_SLEEP_ON_IDLE_RUN
enabled.
Allows control over how the microcontroller invokes IDLE SLEEP function. As a reminder: IDLE SLEEP is considered by Task Scheduler if after checking all the tasks in the execution chain none were found ready to invoke their callback methods. Such run is considered to be an "idle" run. Since Task Scheduler default scheduling resolution is 1 millisecond, such situation means none of the tasks are scheduled as 'immediate', and it is safe to assume nothing will change for the next 1 millisecond.
Under such conditions, Task Scheduler calls a custom supplied method which implements IDLE sleep function specific to a particular microcontroller and/or a use case.
Functional prototype for the callback method is as follows:
SleepCallback customCallback (unsigned long aDeltaTime);
The aDeltaTime
variable is set to the number of microseconds TaskScheduler was active in the
execution pass. This time interval could be evaluated by the callback method to perform a
more precise scheduling.
Please refer to example 23 for details.
void enableAll(bool aRecursive= true);
void disableAll(bool aRecursive= true);
enables
and disable
s (respectively) all tasks in the chain. Convenient if your need to enable/disable
majority of the tasks (i.e. disable
all and then enable
one).
If support for layered task priority is enabled
, supplying aRecursive
parameter will enable/disable
higher priority tasks as well (true, default
), or tasks only on this priority layer (false
).
Task& currentTask();
Returns reference to the task, currently executing via execute()
loop OR for OnEnable
and OnDisable
methods, reference to the task being enabled
or disabled
.
This distinction is important because one task can activate the other, and OnEnable
should be referring to the task being enabled, not being executed.
Could be used by callback methods to identify which Task actually invoked this callback method.
void* currentLts();
Returns pointer to Local Task Storage of the task, currently executing via execute()
loop OR for OnEnable
and OnDisable
methods, task being enabled
or disabled
.
void startNow (bool aRecursive= true);
Sets ALL active tasks in the execution chain to start execution immediately. Should be placed at the end of setup()
method to prevent task execution race due to long running setup tasks (hardware initialization, etc.) following task activation.
If support for layered task priority is enabled
, supplying aRecursive
parameter will set immediate execution for higher priority tasks as well (true, default
), or tasks only on this priority layer (false
).
NOTE: if setup()
method does not contain long running tasks, use of startNow()
method is not necessary. Alternatively, all tasks could be enabled after long-running setup()
processes, thus eliminating the need to use startNow()
method.
NOTE: Any tasks which should execute after a delay
, should be explicitly delayed after call to startNow()
method.
long timeUntilNextIteration (Task& aTask);
Inquire when a particular Task is scheduled to run next time.
Returns time in millis
(or micros
) until the next scheduled iteration of a task.
Returns 0
if next iteration is already due (or overdue).
Returns -1
if a Task is not active or waiting on an event, and next iteration runtime cannot be determined.
bool execute();
Executes one scheduling pass, including (in case of the base priority scheduler) end-of-pass sleep. This method should be placed inside the loop()
method of the sketch. Since execute exits after every pass, you can put additional statements after execute inside the loop()
.
If layered task prioritization is enabled, all higher priority tasks will be evaluated and invoked by the base execute()
method. There is no need to call execute()
of the higher priority schedulers explicitly.
Generally, base priority execute will perform the following steps:
- Call higher priority scheduler’s execute method, if provided.
- Ignore task completely if it is disabled.
- Disable task if it ran out of iterations (calling
OnDisable
, if necessary). - Check if task is waiting on a
StatusRequest
object, and make appropriate scheduling arrangements - Perform necessary timing calculations
- Invoke task's callback method, if it is time to do so, and one is provided.
- Put microcontroller to sleep (if requested and supported) if none of the tasks were invoked.
Please NOTE: schedule-related calculations are performed prior to task's callback method invocation. This allows tasks to manipulate their runtime parameters (like execution interval) directly.
bool isOverrun();
If library is compiled with _TASK_TIMECRITICAL
enabled, this method returns true if currently invoked task has overrun its scheduled start time when it was invoked. Returns false if task has been invoked according to schedule.
void setHighPriorityScheduler(Scheduler* aScheduler);
If library is compiled with _TASK_PRIORITY
enabled, this method associates current scheduler with a higher priority scheduler.
NOTE: Only one execute()
method needs to be explicitly called in the main loop()
. That is the execute method of base priority scheduler. All higher priority schedulers are called by the base priority scheduler.
static Scheduler& currentScheduler();
If library is compiled with _TASK_PRIORITY
enabled, this method returns reference to a scheduler, which invoked current task.
NOTE: Please refer to examples 11 and 12 for illustration of Task Priority functionality
TASK_SECOND
(1.000
millis or 1.000.000
micros) Task interval of 1 second
TASK_MINUTE
(60.000
millis or 60.000.000
micros) Task interval of 1 minute
TASK_HOUR
(3.600.000
millis or 3.600.000.000
micros) Task interval of 1 hour
TASK_FOREVER
(-1
) Task number of iterations for infinite number of iterations
TASK_ONCE
(1
) Task single iteration
TASK_IMMEDIATE
(0
) Task interval for immediate execution