Will this free up memory correctly?

BlitzMax Forums/BlitzMax Programming/Will this free up memory correctly?

Grey Alien(Posted 2006) [#1]
Hi,

If I have a TParticle Type that I create an instance of, and I also have an instance of a TTracker type that has a TParticle field which I point to the instance of the TParticle, then I add the instance of the TTracker Type to a list (still with me?) then later on I do List.Remove(t) where t is my TTracker type instance, will the field within it which points to the TParticle type be freed so that the TParticle will now be freed by the garbage collection properly? I hope so. Trying to think how I can diagram this in text. Anyway here's some example code (tested it compiles):

Type TParticle
End Type

Type TTracker
  Field p:TParticle
End Type

Type TTrackerList extends TList
  Method AddNew:TTracker(p:TParticle)
    Local t:TTracker = new TTracker
    t.p = p
    AddLast(t)
    return TTracker
  End Method
End Type

Global trackerlist: TTrackerList = new TTrackerList

Add()
Remove()

Function Add()
  local p:TParticle = new TParticle
  trackerlist.addnew(p)
End Function

Function Remove()
  For t:TTracker = eachin trackerlist
    trackerlist.remove(t)
  Next
End Function


I know I could code this a different way, but I need it this way for a specific purpose and I just want to check that the memory will be freed up properly. Any ideas?

Thanks.


Dreamora(Posted 2006) [#2]
There is no reason it should not free properly as there are no cyclic references that could keep anything alive.


Grey Alien(Posted 2006) [#3]
that's what I thought, cool + I just tested it in-game and watched the memory counter as I made tons of particles, seems to be OK.


DStastny(Posted 2006) [#4]
Couple things Grey. Not sure I understand what your Remove is doing but it is freeing the entire list. So you could just all trackerlist.clear()

That method removes all the tlinks so all the Particles get marked for collection and its faster than a foreach remove.

Also when adding to a TList like this use AddFirst as AddLast the entire TList needs to be run before the object will be appended so if you have a 1000 particles the entire list will be scanned before you add the 1001st particle.

Another suggestion is to not use a TList at all but create your own link structure and create Particle pools. One pool for active particles and one for for inactive particles. That way you allocate the max you want up front. Speed wise it blows away a TList.

My DX9 Driver demo uses the technique.

Doug Stastny


AlexO(Posted 2006) [#5]

Also when adding to a TList like this use AddFirst as AddLast the entire TList needs to be run before the object will be appended so if you have a 1000 particles the entire list will be scanned before you add the 1001st particle.



Is this really the case? I remember looking at TList a while ago and vaguely remember it being a doubly-linked list where the previous of first (head) would point to the last. Hence when addlast() is called it just goes to the previous of the first element. I may be wrong though :o.


H&K(Posted 2006) [#6]
Not sure I understand what your Remove is doing but it is freeing the entire list. So you could just all trackerlist.clear()

From experiance of Greys posts he is almost certainly doing somthing else, and has just posted this as a stripped down version. But anyway doesnt list.clear() just loop through the list and remove all the links in the same way as Greys code?


Dreamora(Posted 2006) [#7]
Yes, add last adds the element directly to the end. BMs TList is a cyclic double linked list with a "fake" head element that points to first and last.


DStastny(Posted 2006) [#8]
@H&K - clear just cycles the links and releases them until the head is empty. This is hugely faster than Foreach loop, and then calling remove.

@Dreamora & @Alex O. - I stand corrected, I hadnt looked at it in a while but thought I had seen it doing scans to last node. Might have changed or I might be confused. Thanks for clarification.

Frankly I have given up using TLists for time critical code, due to the way it interacts with Garbage collecion I have found preaollocating and using custom pools completey removes Garbage collection, once I have set everything up. Not to say I never use them I try to avoid them when they have large numbers of elements to process, like Particles. This is standard trick for dealing with Garbage Collected languages, .NET, D++, C++ with a Garbage Collector. They make everything easy at the expense of random bumps in performance. But nothing a lttle coding cant work around.

Doug Stastny


Grey Alien(Posted 2006) [#9]
Thanks. H&K is correct, that was just an example, what happens is there is a manage() method where the list is looped and depending on certain conditions remove() may be called. Normally I use clear if I want to clear the whole list.

Budman: Yeah pooling is the way to go for particles but I wanted to write an OOP version using lists first. Pooling is more old-school (sort of like I used to code on the Amiga) but faster of course - I may well do it as an alternative option in my framework. Also I want several lists at the moment so they can be drawn in a certain order (layers), with one big pooled list I couldn't do this, I'd have to make several pooled arrays which gets messy if they are declared globally as the handling routines can't be generic, or maybe they can...hmm.


dmaz(Posted 2006) [#10]
Re: pooling...
http://www.blitzbasic.com/Community/posts.php?topic=62667


JoshK(Posted 2006) [#11]
Always use addfirst. By definition, temporary objects will get sorted towards the front of the list for faster access, and permanent objects will get sorted to the end.


Grey Alien(Posted 2006) [#12]
I see, thanks. Well to be honest all the objects in my list are temporary so it's not an issue.