"ratish" wrote:
"RokuMarkn" wrote:
Seems like you're doing some unnecessary work there. Memory management is based on reference counting the objects, so unless you have circular references, you can just drop the reference to the top level object. If it contains any references to other objects, those will also be deleted when the referring object is destroyed and thus no longer refers to them. There shouldn't be any need for your OnClose function.
--Mark
If my understanding is correct, does it mean calling controllerObj1 = invalid in main() would be enough to release the memory allocated by this and its elemenst such as id, listeners etc?
In this case, that is correct. However, if there was a circular reference within controllerObj1, you would be leaking memory. Consider the following example:
Controller.brs
Function InitializeController()
this = {
id:"controller1"
Listeners:CreateObject("roAssociativeArray")
addListener:CTRL_AddListener
onClose:CTRL_OnClose
}
return this
End Function
Function CTRL_AddListener(keyName, value)
m.Listeners.AddReplace(keyName, value)
End Function
Function CTRL_OnClose()
for each obj in m
if (type(m[obj]) <> "roFunction") or (type(m[obj]) = "roFunction" and obj <> "onclose") then
m[obj] = invalid
m.Delete(obj)
end if
next
End Function
Main.brs
sub Main(argArr = invalid as Dynamic)
' ----------------------------------------------------------------------
' Scenario #1
controllerObj1 = initializeController()
controllerObj1.addListener("listener1", function() as Void
?"Listener 1 executed"
end function)
' ***** SNIP some operations *****
' Invalidate controllerObj1, this causes garbage collection.
controllerObj1 = invalid
' ----------------------------------------------------------------------
' Scenario #2
controllerObj2 = initializeController()
controllerObj2.addListener("listener1", controllerObj2) ' Create circular reference. (controller references itself)
' ***** SNIP some operations *****
' Invalidate controllerObj2, this will leak since controllerObj2 has
' a circular reference.
controllerObj2 = invalid
In the second scenario the controller has a reference to the AA, which has a reference to the controller, which has a reference to the AA, which... etc. In order to allow garbage collection, the circular reference must be broken. In this case, you could simply clear the AA. You may find it valuable to add a common destructor interface which handles any necessary deletion. Something like this:
Controller.brs
Function InitializeController()
this = {
id:"controller1"
destroy:CTRL_Destroy
Listeners:CreateObject("roAssociativeArray")
addListener:CTRL_AddListener
onClose:CTRL_OnClose
}
return this
End Function
Function CTRL_AddListener(keyName, value)
m.Listeners.AddReplace(keyName, value)
End Function
Function CTRL_OnClose()
for each obj in m
if (type(m[obj]) <> "roFunction") or (type(m[obj]) = "roFunction" and obj <> "onclose") then
m[obj] = invalid
m.Delete(obj)
end if
next
End Function
Function CTRL_Destroy()
m.Listeners.clear()
End Function
Main.brs
sub Main(argArr = invalid as Dynamic)
' ----------------------------------------------------------------------
' Scenario #2 with destruction
controllerObj2 = initializeController()
controllerObj2.addListener("listener1", controllerObj2) ' Create circular reference. (controller references itself)
' ***** SNIP some operations *****
' Allow the controller to perform cleanup and break circular references
controllerObj2.destroy()
' Invalidate controllerObj2, this will cause garbage collection.
controllerObj2 = invalid