Page 2 of 2

Re: [BUG]Associative Arrays

Posted: 07 Jan 2018, 13:12
by _3D_
Helgef wrote:Hello _3D_ :wave:

Code: Select all

class Helgef {
	static del:= func("__Helgef_del")
	__delete() {
		msgBox("__delete")
	}
}
__Helgef_del(byRef this, byRef that:= "") {
	if type(this) != "Class" ;prevent class remove
		this:= ""
	that:= ""
}	

var:= new Helgef()
var.del()				;<<< 1 __delete
var:= new Helgef()
Helgef.del(var)			;<<< 2 __delete
var:= new Helgef()
var.del(var)			;<<< 3 __delete
:beer: :beer:

Re: [BUG]Associative Arrays

Posted: 09 Jan 2018, 13:13
by Helgef
That is a classy example :)
helgef wrote:the benchmarking is flawed
Your benchmarking script has been debugged by just me, see here. You missed the little detail that the enumerator from one of the tests holds a reference to the same object as Task.List, hence, Task.List := [] didn't cause the desired outcome, you need to do _enum := "" first ;). You can also remove the timeout msgBOX after Task.List := [], there is no destruction in background when the msgBOX line is reached, it is already done.

Cheers.

Re: [BUG]Associative Arrays

Posted: 11 Jan 2018, 07:40
by _3D_
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.