arkhipenko / TaskScheduler

Cooperative multitasking for Arduino, ESPx, STM32, nRF and other microcontrollers
http://playground.arduino.cc/Code/TaskScheduler
BSD 3-Clause "New" or "Revised" License
1.23k stars 224 forks source link

Added Scheduler::executeBacklog(size_t noTasks) #56

Closed BlackEdder closed 5 years ago

BlackEdder commented 6 years ago

This method executes upto the given noTasks from the backlog.

It's a helper function to make it easier to empty the backlog in the queue

BlackEdder commented 6 years ago

An alternate implementation would return the number of tasks executed

return i - 1;
arkhipenko commented 6 years ago

It's an interesting idea, but I need to understand what you call a backlog. I might have a task that is scheduled to run every time. Would that be a backlog? Since execute() should be running in the loop() without delays, it is already trying to clear up the backlog as soon as possible. What are you trying to achieve with this method?

BlackEdder commented 6 years ago

I had indeed not considered a task that is scheduled to run every time.

What I meant with backlog is all the task that are out of time. Say I have two task that should run in 100ms. Now after 101ms I run scheduler.execute() only one of those tasks would be run. With the executeBacklog() both of those tasks should be executed.

The background of why I needed this is that someone using painlessMesh managed to overload the scheduler by every loop calling a library function that resulted in more than 1 action (task) being added to the scheduler, while of course only calling execute once per loop. As a result the scheduler never caught up.

You could argue that this is the user misusing the library/scheduler, but I'd rather guard against this problem if possible :)

arkhipenko commented 6 years ago

I am still not sure this will solve the problem though... The scheduler's execute () method will run through the entire chain of tasks and invoke all that are ready to be started, including the tasks that were dynamically added to the execution chain after the current task. What execute() does not do is invoke the task again and again if that task is still late for the following run, because in this case that one task will never give anyone else a chance to run.

Again, I am going on an assumption that you run execute() continuously without interruption. If that is not the case, then it's not the intended use indeed - 'execute()' is a "heartbeat" of TaskScheduler, and should not be paused.

So under the assumption of continuous uninterrupted calls to execute() how would a separate loop to call execute() N times be different from calling it continuously? It is already trying to attend to all tasks as fast as it could.