Long time I think why I chose iteration instead of just simple reference cleaning?
https://lexikos.github.io/v2/docs/Objec ... e_Counting
Known Limitations:
Circular references must be broken before an object can be freed. For details and an example, see Freeing Objects.
Although references in
static and global variables are released automatically when the program exits, references in non-static local variables or on the expression evaluation stack are not. These references are only released if the function or expression is allowed to complete normally.
Although memory used by the object is reclaimed by the operating system when the program exits, __Delete will not be called unless all references to the object are freed. This can be important if it frees other resources which are not automatically reclaimed by the operating system, such as temporary files.
How the mechanism work:
1. If only one reference is stored into variable - when script exit we have guaranteed call of __delete()
Code: Select all
class class_Test_1 {
__new(name) {
this.name:= name
}
__delete() {
msgBox(type(this) " >>> " this.name)
} }
var:= new class_Test_1("auto")
msgBox("exit")
ExitApp ; <<< auto call class_Test_1.__delete()
It work perfect and calling is guaranteed.
2.
If only one reference is stored inside object (as static or local) - no auto release for last reference => no call of __delete()
Code: Select all
class class_Test_2 extends class_Test_1 {
static reference:= ""
__new(name) {
class_Test_2.reference:= this
base.__new(name)
} }
new class_Test_2("forced") ; <<< only one reference is stored into static variable
msgBox("exit")
;class_Test_2.reference:= "" ; <<< must forced be cleared (UNCOМMENT TO CALL __delete())
ExitApp ; <<< class_Test_2.reference must be forced cleared
In this case even one only reference no call of __delete(). To call __delete() internal static variable that contain reference must be forced clear.
Conclusion:
If we need to guarantee executing of on destruction actions we need:
1. Clear all references inside objects.
2. Forced run on destruction actions.
3. Have some mechanism that prevent second run of on destruction actions (not mandatory).
Code: Select all
Task.List:=[] ;no guarantee to call __delete() for all
It mean at this time (doubled references will be released when script done or when references will be released).
Code: Select all
while !isEmpty {
isEmpty:= 0
for key in Task.List {
key.end()
isEmpty:= 1
} }
In this case we have guaranteed calling of __delete() (in some cases twice) at the time.