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.33k stars 243 forks source link

? setInterval bug when called at a higher frequency than the interval. #94

Closed sticilface closed 4 years ago

sticilface commented 4 years ago

https://github.com/arkhipenko/TaskScheduler/blob/c1e4e272db2587df38baa62974d0106c63219eeb/src/TaskScheduler.h#L593

I think this should only call delay() when the interval is actually changed? At the moment if you call it faster than the interval it is constantly pushed into the future and never executed?

void Task::setInterval (unsigned long aInterval) {
   if ( iInterval != aInterval) {
    iInterval = aInterval;
    delay(); // iDelay will be updated by the delay() function
   }
}

What do you think?

arkhipenko commented 4 years ago

Nope. This is the intended behavior. https://github.com/arkhipenko/TaskScheduler/wiki/API-Task#void-setinterval-unsigned-long-ainterval

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.

arkhipenko commented 4 years ago

The dilemma is: what happens when you change the interval?

  1. Let's say you are in the task callback and you changing interval for "yourself" so to speak. Then the next invocation is supposed to happen after a current interval. In this case, it makes sense to delay execution using a new interval (sort of putting the new interval in effect)
  2. Let's say a task is changing interval for the other. Anything is possible at this point - the affected task may just finished its callback, could be in the middle somewhere, or about to be invoked. The elaborate way of course would be to pro-rate the current interval (or what's left of it). I never needed such functionality, but it is possible to do using this method: https://github.com/arkhipenko/TaskScheduler/wiki/API-Task-Scheduler#long-timeuntilnextiteration-task-atask You can also invoke immediately, but it might not be what the process expects. So I chose to delay. Any corner cases - you can change the behaviour right after the call to setInterval.

Makes sense?