"Null" dead Object

BlitzMax Forums/BlitzMax Beginners Area/"Null" dead Object

Yue(Posted 2015) [#1]
I have a concern. As I quite understand to release an object that occupies space in the memory is not as Blitz3D where used "Delete" now rather use "Null" if within the fields of the type I have a field to create a window, using null the object value of this field automatically deletes the window?

'Clase Ventana
'==============
Type Wind

	Field ventana:TGadget  =  CreateWindow("Ventana Principal",0,0,500,500,Null,WINDOW_DEFAULT|WINDOW_CENTER) 

	
	
	Function Crear:Wind()
	   
		
	
	 	Return  New Wind
			
		 
	End Function 

End Type 


Import MaxGui.Drivers

' Ficheros incluidos.
Include "Clases.bmx"


Local evento:Int 
Local ventana:Wind = Wind.Crear()







Repeat 

 evento:Int = 	WaitEvent()
	
	Select evento:Int
		Case EVENT_APPTERMINATE, EVENT_WINDOWCLOSE
			Exit
	End Select



Forever
ventana = Null ' Delete obj ventana and Fields too?




kfprimm(Posted 2015) [#2]
No. However, if you add this to your class:

Method Delete()
    FreeGadget ventana
End Method


The gadget will be freed as soon as the garbage collector collects the instance. This will not be immediate.

You are probably better off to implement a Free method in your class that will free the windows, along with whatever else you may need to do. Call that, then set the variable to Null.


Yue(Posted 2015) [#3]
@kfprimm
Thanks You.

'Clase Ventana
'==============
Type Wind

	Global  ventana:TGadget  

	
	
	Function Crear:Wind()
	   
		ventana:TGadget  = CreateWindow("Ventana Principal",0,0,500,500,Null,WINDOW_DEFAULT|WINDOW_CENTER) 
	
	 	Return  New Wind
			
		 
	End Function 

End Type 

Global ListaWind:TList = New TList

Import MaxGui.Drivers

' Ficheros incluidos.
Include "Clases.bmx"


Local evento:Int 
Local W:Int[10]

For Local n:Int=0 Until 3
   
   W:Int[n] = Wind.Crear() ' Create 3 Obj Type Wind
    
Next 


For Local x:Int=0 Until 3
			listaWind.addlast New  Wind
Next

'Only delete one obj Ventana...
For Local o:Wind=EachIn listaWind


 	If o.Ventana Then 
		FreeGadget (o.Ventana)
		ventana = Null 
	EndIf 

Next 




Repeat 

 evento:Int = 	WaitEvent()
	
	Select evento:Int
		Case EVENT_APPTERMINATE, EVENT_WINDOWCLOSE
			Exit
	End Select



Forever

ventana = Null



As I come from Blitz3D I hope some things work equal to Blitz3D, but apparently it's not that way.

In the above example I only eliminates a single window, when expected to eliminate the three.

what am I doing wrong?


Henri(Posted 2015) [#4]
Hi,

here is a example of one way of doing it:



-Henri


col(Posted 2015) [#5]
As you are learning OO, at first as a beginner don't use Function or Global inside a Type just yet, until you understand how OO works. It may be too fast for learning and could be confusing you.

This code uses an easy way to understand OO for a beginner.
You need to have a new vertana owned by each new Wind.

Strict ' VERY important
Type Wind
	Field ventana:TGadget

	Method Crear()
		ventana = CreateWindow............
	EndMethod

	Method DestroyWindow()
		FreeGadget(ventana)
	EndMethod
EndType

For Local o:Int = 0 Until 3
	Local W:Wind = New Wind
	W.Crear()

	ListAWind.AddLast(W)
Next

For Local o:Wind=EachIn listaWind
 	If o.Ventana Then
		o.DestroyWindow()
	EndIf
Next



col(Posted 2015) [#6]
To help don't forget there is a debugger. A little tutorial for using the debugger.
The debugger is a HUGE help to find problems like you are having above.

edit: Don't use Null and expect the object to be deleted immediately. BlitzMax uses garbage collection for managing memory. The garbage collector is intelligent in that it will run only when it needs to. If you need to guarantee to free a gadget at a certain time then use a Method in the type to free the gadget and call the method - its the only way to know that the gadget is really freed at the same time as when you want to destroy the Window. The Window will be free later when the garbage collector wants to free it even though you can't use it any more. Trust it :-)


Yue(Posted 2015) [#7]
Hi, I appreciate the help, I'm slowly getting it.

My question is how removed with a "For", various objects, without having to do it manually for each of them.


Type Car
  Field id:Int = 1500
End Type 


C:Car = New Car
C.Id = 1800

C2:Car = New Car
C.id = 1300


Print c.id
Print c2.id

C= Null
C2 = Null 

' For ... EachIn  delete all obj ??





Henri(Posted 2015) [#8]
No, let's throw the man in the ocean and see if he can swim :-)

Global inside a type is practically the same as global outside (a static variable accessable from every part of your program). Only difference is that if global is inside a type you have to use the type name (namespace) before the variable name like <typename>.<global variable>.

-Henri

Ps. Using int handles (instead of TGadget) is probably not a good idea if he ever wants to try Brucey's 64bit version.


markcw(Posted 2015) [#9]
In Bmx there is a garbage collector (GC) so you don't have to delete any objects manually, they get deleted automatically when they go "out of scope".

I think you do something like call GCResume but I'm not very good with the GC commands, maybe someone will explain better.


Yue(Posted 2015) [#10]
Well, they said the case, in Blitz3D. to something like this.


for obj.TypeMesh = each TypeMesh

   if obj\Mesh then
       FreeEntity obj\Mesh%
   End if 

   Delete obj.TypeMesh
Next

For some reason I think I have to remove the object, because in Blitz3D under certain circumstances if not eliminated problems caused, for example in changing screen resolution, which had to carry an entire scene again.

I appreciate someone explain to me the garbage collector BlitzMax.


markcw(Posted 2015) [#11]
To explain globals/functions, if outside a type you use global/local and inside a type you use global/field. Global in a type only exists once (used for eg. mytype_counter) and fields are per instance/occurence (for eg. mytype_xpos).

Functions are like globals in that they exist once (even before any instance of that type exists) but methods are instance based, like fields. So to access globals/functions you would use TypeName.Func() or TypeName.global but with fields/methods you use myinstance.Meth() or myinstance.field. The equivalent to globals/functions in C++ is called static - in that their locations don't change at runtime.


Henri(Posted 2015) [#12]
If a type has a more complex freeing mechanism like for example TGadget type has a FreeGadget() then this should always be used instead of just nulling the variable. Otherwise there are bound to be problems. Probably FreeEntity falls to this category.

It is customery to put a freeing mechanism (I use Free function or Method) to your types to do the cleaning work.



Officiale introduction to GC:
BlitzMax uses a technique known as reference counting to keep track of objects that are in use by your program.

The basic idea behind reference counting is that each object includes a counter reflecting the number of variables referencing that object. When an object's counter reaches 0, the object is no longer in use and its memory can be returned to the system.

The process of returning unused objects to the system is called 'garbage collection' and, by default, is performed automatically. However, it may be desirable to 'force' a garbage collection (for example, to check for memory leaks) and this can be done using the GCCollect command



-Henri


col(Posted 2015) [#13]

My question is how removed with a "For", various objects, without having to do it manually for each of them.


The garbage collector knows these things, and will do it for you :-)

Behind the scenes of a garbage collector... there are many many different ways of doing it. BlitzMax uses reference counting. For eg if inside a function you create an instance of Local c:Car = New Car then 'c' will have an internal reference of 1 ( you don't know how many references there are - its internal in BMax objects that you cannot access ). If you then put that new car into a TList it will have a reference of 2. When the Local c:Car is no longer accessable ( by leaving the function ) then the reference count will drop to 1. When the TList goes out of scope and can no longer be used then that c:Car reference will be 0 and will be given to the garbage collector to free it when the garbage collector feels like it. Its way more complicated really but it gives you and idea. Every object in BlitzMax works that way.


Yue(Posted 2015) [#14]

The BASICs
First up, let's have a look at what Blitz3D's Delete command actually does. It really serves 2 purposes:

The object is removed from its 'type list'.
The memory used by the object is returned to the system - this is called 'deallocating' the object.
Step 1 is necessary due to Blitz3D's type list system, which automatically adds all New-ed objects to an internal global type list.

Step 2 is necessary to prevent memory leaks. A memory leak is when your program has allocated a chunk of memory, used it for something, and then forgotten to deallocate it when it is no longer useful. Since computers have a finite amount of memory, this will eventually cause problems if it happens often enough!

The first thing about these 2 steps to note is that the global type list system is no longer present in BlitzMax, so step 1 is now completely up to the user - if you have added an object to a linked list (or lists), it is up to you to remove it.

If all you are wanting to achieve is a system similar to Blitz3D's type list system, then this is as simple as using ListAddLast immediately after you have created an object using New, and using ListRemove immediately before deleting it using Delete - oops, there is no Delete! Ok, using ListRemove *instead* of Delete!

This still leaves the question of deallocating the object's memory, and this is done in BlitzMax using a 'garbage collector'. A garbage collector automatically scans for 'dead objects' every now and then and releases the memory they occupied.

Note that the issue of deallocating objects is completely separate from the issue of type lists. Yes, if you forget to remove an object from a list it will remain 'live', but this is the same as forgetting to delete an object in Blitz3D!

One final complicating issue: BlitzMax includes a feature that allows you to assign objects to integers. This feature exists mainly to simplify things for beginners so, instead of...



I think I'm slowly getting it.


col(Posted 2015) [#15]

No, let's throw the man in the ocean and see if he can swim :-)



He's swimming :O)


I think I'm slowly getting it.


The thing is that it's so easy... too easy... makes it difficult :D


col(Posted 2015) [#16]
Heres an example of forcing the garbage collector to work. Note the first time it is called that the memory of the New'ed object may not be collected! After creating a 2nd new TList and filling it, then calling the GCCollect then you may get messages from the Delete method - proving the garbage collector is actually deleting your New'd type for you!! If you don't get messages then just up the 1000 to something higher to eat up more memory.
During a regular program GCCollect is automatically called for you and you can forget about memory management when using BlitzMax ( although it's good to be aware of cyclic referencing, and don't do it if you don't have to )

To use BlitzMax you don't need to know how GC works, just be peaceful that it works. But as you are curious...

' Force a garbage collection in action :-)
Type tl
	Method Delete()
		Print "Deleting"
	EndMethod
EndType
Type t2
EndType

Local l:TList = New TList
For Local i = 0 Until 1000
	l.addlast(New tl)
Next

' The GC may or may run when l = Null? who know's - try it
l = Null
Print "Running the garbage collector manually"
GCCollect() ' This is done automatically - no need for us to call it at all
Print "Finished collecting"
' you may not get any deleting messages because BlitzMax doesn't need the memory at this point!


l = New TList
For i = 0 Until 10000
	l.addlast(New t2)
Next
l= Null

Print "Forcing garbage collection for the 2nd time"
GCCollect()
Print "Finished forcing the collection"
' you may get 'deleting messages now' because internally BlitzMax wants the memory back from the first list


You can put the loops inside a function and remove the GCCollect too to see that the GC is automatically working for you :-)


' Force a garbage collection in action :-)
Type tl
	Method Delete()			' internally called when being deleted!
		Print "Deleting"
	EndMethod
EndType
Type t2
EndType


Function ICannotWasteMemory()
	Local l:TList = New TList
	For Local i = 0 Until 1000
		l.addlast(New tl)
	Next

	' l:TList goes out of scope here and will be deleted automatically
	' including any of its own internal TNode objects and of course any object instances stored that we created and have stored in the TList,
	don't know when though, but it will definitely be deleted at some point now or later - cool eh
EndFunction

Print "First"
ICannotWasteMemory()
Print "Second"
ICannotWasteMemory()
Print "Third"
ICannotWasteMemory()



Yue(Posted 2015) [#17]
Ok, no problem here.
I have still much to learn. In a way I think I look like a scout deciphering Maya writing. :D