How to check if a type object is dead?

BlitzMax Forums/BlitzMax Programming/How to check if a type object is dead?

Robert Cummings(Posted 2006) [#1]
Hiya, here's a little OO challenge for you:

Field preyType
	Field x,y:Int
End Type

Type hunterType
	Field x,y:Int
	Field prey:preyType
End Type


The hunter stores a reference to the prey with self.pray = p (if looping through preys and choosing one).

It does this so the hunter can access the prey objects data with a pointer to it (or is this a reference to it?)

Within the hunterType update code, I go: If self.prey = Null Then find new prey.

However even when I remove the prey object, it is never null when the hunter checks his prey field? How do I detect when it no longer exists?


AntonyWells(Posted 2006) [#2]
Create a list and remove objects from it in the delete method.

Type Pray

Method Delete()
AliveEntities.Remove( Self )
end method

end type


Grey Alien(Posted 2006) [#3]
When you say "remove the prey object". How are you doing that? By setting it to null and calling GCCollect (seeing as Delete is a reserved work)? Any other method isn't removing it and thus the prey field in unter won't be null. Maybe anyway, it doesn't go null after Garbage Collection anyway, shame. Another naff way is to have a pointer to Hunter in Prey and when you "remove" prey, set the Prey Field in Hunter to Null manually.


TomToad(Posted 2006) [#4]
Type preyType
	Field x,y:Int
        Field Dead:int = False
End Type

Type hunterType
	Field x,y:Int
	Field prey:preyType
End Type

Local Squirrel:preyType = new preyType
Local Hawk:hunterType = new hunterType

Hawk.prey = Squirrel

Squirrel.Dead = True
Squirrel = Null

If Hawk.prey.Dead = True then Hawk.prey = Null


Seems to work ok.


Grey Alien(Posted 2006) [#5]
For safety I would change the last line to:

If Hawk.prey <> Null then
If Hawk.prey.Dead = True then Hawk.prey = Null
EndIf

because if Garbage Collection does null the pointer at some future point, Hawk.Prey.Dead will crash as it references a field of a null object.

If BlitzMax had "incomplete boolean evaluation" like Delphi you could put it all on one line:

If Hawk.prey <> Null and Hawk.prey.Dead = True then Hawk.prey = Null


Because the code wouldn't bother to evaluate the second part (Hawk.Prey.Dead) if the first part returned True. This is neat and fast and I Wish BMax supported it, but it doesn't, I've tested it. Wait a minute I tested in BPlus not Max. Perhaps Max DOES support it.


TomToad(Posted 2006) [#6]
Grey: GC will not set the pointer to Null because after you set Squirrel to Null, there's still a reference to it in Hawk. If the GC deletes Squirrel while Hawk is still referencing it, then that would be a bug in BMax. However, you're added code is still a good idea just in case Hawk.prey hasn't yet been set to point at anything.

Also, BlitzMax does have incomplete boolean evaluation. Try this and you'll see. :)



Grey Alien(Posted 2006) [#7]
OK Thanks TomToad, of course I should have realised that. Generally I like to test for null to avoid problems if I suspect something may have been a)not created yet or b)been destroyed already.

Oh and thanks for the code example that shows that BMax DOES indeed have incomplete bool eval!


Robert Cummings(Posted 2006) [#8]
Just to clarify this:

until my hunter's prey field is cleared, then the prey object will not be garbage collected?

So it'll never be null until all other things in memory looking at it's address are also null?


Grey Alien(Posted 2006) [#9]
yes, that's my understanding of it (since about yesterday :-)) Because the garbage collector keeps track of how many variables point at the type. So you've got 2: the actual prey object and the variable in the hunter object. You free up the prey object (null it, whatever), but you still have 1 variable in hunter pointing at it so the GC won't get rid of it yet, even though the original object variable is null.


Robert Cummings(Posted 2006) [#10]
Thats really clever really I suppose. I recall having a nightmare time with C++ GC.


sswift(Posted 2006) [#11]
Create a list for your hunters. A field in the hunter type Global HunterList:TList.

When you create a hunter, add it to this list.

Have a method in the prey type you call for the prey when it is killed.

In that method, loop through all hunters in the hunter list with eachin, and check to see if Hunter.Prey = Self. If so set Hunter.Prey to Null.

Now assuming that you have no other pointers in your program pointing to the prey, the prey will be removed as soon as the method ends.

If you have a list of prey, then you will need to remove the prey from that list in that method.

Also, now that the hunters are in a list you will need to remove them from the list when you want them to be deleted.