Execution of handlers in library classes

When browsing through the classes such as Bullwinkel on Github, I noticed that instead of calling provided handlers directly, ,eg

handler();

the developer often used an imp_wakeup construct with zero timelapse =>

` imp.wakeup(0, function() {handler(); });`

What is the benefit of doing it like that ? Does it actually consume a timer, even if it’s for a very short timeperiod ?

As an off-topic but related remark, I’m always trying to avoiding timer creation as much as possible as I’m have been flirting with the 20 timer limit and already spend days debugging errors that in the end originated from surpassing this limit at some point in time (which results in random halting of recursive imp.wakeup constructs that are intended to continuously repeat themselves, depending on which one wanted to ‘renew’ when the limit was hit). I am using a central timer factory using a single timer for most purposes in my own code and classes, but then still 20 is too low…
Glad to see that in the Bullwinkle class V2, this is done as well in the _watchdog(). Unfortunately I’m still using V1 which creates a new timeout timer for every message… When too many messages accidentaly come together, the limit is often reached.

@vedecoid,
running out of timers was an issue for me too. I settled on writing my own code to manage them. I use a single imp.wakeup to manage timers scheduled for some point in the future where I only require rough accuracy, and imp.onidle for things (like your example above) where you would use imp.wakeup(0, …
For anything that requires accurate timing I use the other 18-19 remaining imp.wakeups.

This is just an excerpt, but this part is probably self-contained:
`
timer <- {
_idleJobs = []

// Jobs can be queued here, to be executed when other immediate tasks have been completed.
// add function to idle queue and restore onIdle handler
function whenIdle(func,key=null){
    _idleJobs.push({ func=func, key=key });
    imp.onidle(_onIdle.bindenv(this));
}    

// called when agent is idle
function _onIdle(){ 
    // this may fail if object has expired and been garbage-collected
    while (_idleJobs.len()>0)
        (_idleJobs.remove(0).func)();
}    

// removes all entries with the specified key (ie kills pending jobs under that name)
function filter(key){
    // remove any tasks from queue with this key
    local f = function(index,value){ return value.key!=key }
    _idleJobs = _idleJobs.filter(f);
}

}`

The essence is…
I call timer.whenIdle(handler,“myKey”) when I want to execute something as soon as the agent has finished what it’s currently doing and there may be no need to retain the current context or stack depth. The jobs don’t need to be executed synchronously, they just need to happen as soon as there is cpu time available for them to be done.

Because I often have many dozens of jobs scheduled and the jobs could require cancelling before execution (due to asynchronous events such as a loss of connection with the device), I tag them with a key so I can remove them from the job queue.

(note also that there are no timer limits on the device apart from memory - the 20 timer limit is only on the agent side)