Canceling & nilling timers

I’ve been reading up on how-to-properly-cancel-timers (to avoid memory leaks and other malaise caused by rogue timers), but I’m still not getting it.

I can deal with cancelling/nilling timers if the timers that need cancelling/nilling are the ones that are still in motion.

In other words, it would make things a lot easier if a timer (which is created with timer.performWithDelay) is automatically cancelled and nilled after the timer completes what it’s supposed to do. If that’s the case, I’d only need to worry about timers that needs to be interrupted before completing it’s job.

Does anyone know how the timers are garbage collected? Do they even get garbage collected without being cancelled and nilled?

[import]uid: 67217 topic_id: 14454 reply_id: 314454[/import]

timer.cancel(timer_name) that’s all you have to do. You could also do an onComplete function in the timer.

Regards,
Jordan Schuetz
Ninja Pig Studios [import]uid: 29181 topic_id: 14454 reply_id: 53481[/import]

Thank you, ninjapig123! I really appreciate your help.

So… unless I cancel & nil the timer, it will not get cancelled/nilled nor will it ever garbage collected? The thing is, I use the cancelAllTimers() function that Jonathan Beebe has posted (one of many great functions he has offered for everyone). You can find it here (scroll down to Timers and Transitions section):

http://blog.anscamobile.com/2011/08/corona-sdk-memory-leak-prevention-101/

And this cancelAllTimers() looks like it would cancel and nil out all timers, and I thought it was all I needed to do, until I read an alert that says:

The cancelAllTimers() function should only be used as a cleanup! Please run :cancel() and nil out timers individually before calling cancelAllTimers(), so keep track of them all!

The alert is located here: http://developer.anscamobile.com/code/beebegames-class

I’m not sure what it’s really saying. But I thought, maybe, I can do something like the following to cancel and nil out timers that are piling up on timerStash. Would something like this work?

local function cancelMyTimers()  
 for numLoop=#timerStash,1,-1 do  
 timer.cancel(timerStash[numLoop])  
 timerStash[numLoop] = nil  
 end  
end  

But then, why on earth do I even need to call cancelMyTimers() before calling cancelAllTimers()? What am I missing? I just don’t understand the logic behind the need for what-appears-to-be double cleanup.

I’m probably not seeing something that’s obvious to experts… Maybe the cancelMyTimers() just doesn’t cut it either.

If you can shed light on this, I’d be so grateful.

[import]uid: 67217 topic_id: 14454 reply_id: 53496[/import]

Uh idk, I’ve never used those classes before. I think Ansca has fixed the timer memory leak errors. All I do is cancel each timer using the timer.cancel() function.

Regards,
Jordan Schuetz
Ninja Pig Studios [import]uid: 29181 topic_id: 14454 reply_id: 53497[/import]

Thank you, ninjapig123. I’ll keep looking. The thing is, I have a feeling that timers don’t get cancelled until after it finishes its work. Sometimes I need a timer to be interrupted, cancelled, nilled and completely removed before it completes its job. timer.cancel() doesn’t seem to do what I need it to… [import]uid: 67217 topic_id: 14454 reply_id: 53502[/import]

@ask,
strange, you say that.

generally most code hon the forums does not set a handle to the timers, and most of it called using timer.performWithDelay(…)

instead if you use

hTimer = timer.performWithDelay(…)

and where ever you need to cancel/pause the timer, you can use the timer.cancel or timer.pause, once the timer fires, then the timer handle is not valid and cannot be canceled.

so you can nil the timer handle in the code when the timer fires and also if you were to cancel the timer.

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 14454 reply_id: 53504[/import]

you can use timers in different ways.

  1. usually, you want to track timers by using a handle (like jayantv suggested):
local myTimer  
-- fire myFunction every 100ms endlessly (-1)  
myTimer = timer.performWithDelay( 100, myFunction, -1 )  
-- to cancel the timer, do  
timer.cancel ( myTimer )  

sure, you can add your handlers to a timer stack and iterate through that stack in a killTimers function.
2. but you can also use timer without a variable name. In this case you won’t be able to cancel the timer directly. It will be nilled when the job is finished - ONLY when the job is finished:

-- fire myFunction every 100ms four times  
timer.performWithDelay( 100, myFunction, 4 )  

That means that you need to keep track of your timers by using handlers, if you want to control and change them in runtime.

I don’t know if this what you’re looking for - just thought that it wasn’t exactly explained in this thread, yet.

-finefin [import]uid: 70635 topic_id: 14454 reply_id: 53516[/import]

@jayantv and @canupa – thank you so much for the detailed explanation of the nature of the timer. It helps a lot.

If I need a timer interrupted, it sounds like what I need to do is, after the timer is fired (but before it completes its job), I need to pause the timer in progress, and then cancel it and nil it?

I assign handler to all timers by using the method described in memory prevention 101 – meaning, I have timerStash table (global variable) defined in main.lua:

timerStash = {}

And then whenever I use timer, I do:

timerStash.newTimer = timer.performWithDelay( 100, myFunction )

I don’t usually need the timer to repeat. But there are race conditions where timer is fired but must be interrupted because the player hits playAgain button (which resets the game module) or menu button (which triggers scene change).

So, to pause my timers first and cancel them, would the following work:

local function cancelMyTimers()  
 for numLoop=#timerStash,1,-1 do  
 timer.pause(timerStash[numLoop])  
 timer.cancel(timerStash[numLoop])  
 timerStash[numLoop] = nil  
 end  
end  

Would this cover both timers that have not fired yet and the ones that have fired but hasn’t completed the process?

Thanks again! [import]uid: 67217 topic_id: 14454 reply_id: 53589[/import]

BUMP

So what’s the consensus on this?

Timers that have already completed only need to be nilled but NOT cancelled?
[import]uid: 73951 topic_id: 14454 reply_id: 115062[/import]