realbasic-nug
[Top] [All Lists]

Dangerous deallocation/circular reference...

To: REALbasic Network Users Group <realbasic-nug at lists dot realsoftware dot com>
Subject: Dangerous deallocation/circular reference...
From: Brady Duga <duga at ljug dot com>
Date: Thu, 11 Jul 2002 11:01:09 -0700
I just tried what is either a rather cool and elegant solution to a problem, or a complete hack that only works by pure chance, and I'm trying to decide which of these I have on my hands. Basically, I have a few different objects, of different types, that want to perform some action at regular intervals. They may not all need to be performing these tasks at the same time - that is, they may not need to receive any notification from a timer. Also, they will probably be using different intervals - some things might want to be activated every tenth of a second, others may not need to do any thing for 10 seconds. To implement this functionality, I made a new Tickler class with Timer as super to it and a Tickled class interface with a Tickle method. Now anyone that wants to be updated just needs to implement Tickled->Tickle and create a new Tickler. However, in my implementation, the Tickler references the Tickled and the Tickled references the Tickler, creating a circular reference which can lead to a memory leak. This isn't too big a deal at the moment as all the objects are essentially permanent, and if I really need to toss them I can just break the circular reference.

Now that I have that, I wanted to create a new, temporary object that would live for a limited time frame, but perform some actions during it's life. Say I want it to do something every second, and I want it to do it 10 times. Well, using the Tickler there is a cool way of accomplishing this - just make the object, which implements the Tickled interface and return. So long as the circular reference exists, the object will live, which means I don't need a property to track it. I can start it up in one routine and immediately exit. Then, in the Tickle method of the object, I just set its reference to the Tickler to be nil. This breaks the circular reference, allowing both the Tickler and the Tickled to be deleted. This is kind of interesting, as it lets me create objects with a life of their own - I don't need to track them, they simply live until their task is complete and die when they are finished, independent of their creator.

So, my question is, is this safe? I am worried because the reference count of the Tickler becomes 0 from a call the Tickler is making. So the stack is:

1: RB Timer magic
2: Tickler.Action
3: Tickled.Tickle

when the object that caused 2: to run reaches 0. When is Tickler actually released? When its refcount hits 0? When new memory is allocated? And does RB know not to delete an object which is involved with the current call-chain? I suppose I could have the Tickler break the circle instead, after the call to the Tickled, but I need to have some way of communicating that from the Tickled, which is the object that knows when the task is complete...

--Brady
The La Jolla Underground



<Prev in Thread] Current Thread [Next in Thread>