Discussions related to Visual Prolog
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Finalizer executed too often

Unread post by Martin Meyer »

Hello Thomas,

please check below code (in VIP 7.5.0.2).

Code: Select all

interface myObj end interface myObj   %---   class myObj : myObj     constructors         new : (integer Num). end class myObj   %---   implement myObj     facts         num : integer.       clauses         new(Num) :-             num := Num,             stdIo::write("created object ", num, "\n").       clauses         finalize() :-             stdIo::write("finalized object ", num, "\n"). end implement myObj   %===   implement main   class predicates     createObject_nd : () nondeterm. clauses     createObject_nd():-         N = std::cIterate(3),             _ = myObj::new(N).   clauses     run() :-         createObject_nd(),             fail.     run().   end implement main
In my test the finalizer was executed more often than the object had been created. It has output

in 32-bit mode:

Code: Select all

created object 0 created object 1 created object 2 finalized object 1 finalized object 0 finalized object 1 finalized object 2
and in 64-bit mode:

Code: Select all

created object 0 created object 1 created object 2 finalized object 2 finalized object 1 finalized object 0 finalized object 0
Regards
Martin
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

Thank you. I get the same result, we will look at it.
Regards Thomas Linder Puls
PDC
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

As far as I can see each object are indeed only finalized once each.

What you see is a strange behavior in the console output stream. I am not sure what happens. However finalization run at "strange" times. Therefore it can intrude/enter/reenter other code at strange points, much in the same way as when several threads run in parallel. Streams are not thread safe and hence they are not "finalizer safe" either.

This code:

Code: Select all

implement myObj     open stdio   class facts     newCnt : integer := 0.     finalCnt : integer := 0.     m : (string M).   facts     num : integer.   clauses     new(Num) :-         num := Num,         write("created object ", num, "\n"),         newCnt := newCnt + 1.   clauses     finalize() :-         M = string::format("finalized object %\n", num),         write(M),         assert(m(M)),         finalCnt := finalCnt + 1.   class predicates     createObjects : (). clauses     createObjects() :-         foreach I = std::cIterate(3) do             _ = new(I)         end foreach.   clauses     test() :-         createObjects(),         memory::garbageCollect(),         writef("newCnt = %\nfinalCnt = %\n", newCnt, finalCnt),         foreach m(M) do             writef("> %", M)         end foreach.   end implement myObj
produces this output in my case:<pre>created object 0
created object 1
created object 2
finalized object 0
finalized object 1
finalized object 0
newCnt = 3
finalCnt = 2
> finalized object 1
> finalized object 0
finalized object 2</pre> which is consistent with one finalization per object (but still two messages for one of the objects).
"object 2" is not finalized until after my "test writing".

I will advise you only to use finalizer's for releasing external (and with care also internal) resources.
Regards Thomas Linder Puls
PDC
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer »

Thanx Thomas for the explanation!

Regards
Martin
Post Reply