Esteban wrote:
>you also need to register the object for cleanup, in the WeakRegistry. >(not on my machine, sorry I cannot put an example, but look around) It is simple and here is an example: Create a class: Object subclass: #Bar instanceVariableNames: 'id' classVariableNames: '' category: 'Foo' implemented an #initialize method initialize super initialize. id := UUID new. Transcript show: 'Initialized ', id printString; cr and implemented a finalization method: finalize Transcript show: 'Finalized ', id printString; cr Now in the workspace I instantiate the object: |anObject| Transcript open; clear. anObject := Bar new. Transcript flush. WeakRegistry default add: anObject. and by forcing garbage collection in a second step I can see that the finalization method is working: 3 timesRepeat: [ Smalltalk garbageCollect ]. Transcript flush. And I get the following output Initialized 4aa47ef1-0e4c-9a47-bddf-b406ee2042e4 Finalized 4aa47ef1-0e4c-9a47-bddf-b406ee2042e4 If it doesnt work check your VM for updates. I'm using Pharo4.0 Latest update: #40442 on Windows with the following VM: Win32 built on Sep 4 2014 01:13:32 Compiler: 4.6.2 VMMaker versionString https://github.com/pharo-project/pharo-vm.git Commit: c7bc23dd6053d5f9934f7dd427537f76fc96eb32 Jenkins build #14851 |
Yes, adding it to the weak registry does the trick! Thank you Esteban for the pointer and Torsten for the magic line of code WeakRegistry default add: anObject. Being able to hook into the GC in this way is extremely cool, it saves me a lot of housekeeping work and I am very happy because of that ! > On Jan 13, 2015, at 17:35, Torsten Bergmann <[hidden email]> wrote: > > Esteban wrote: >> you also need to register the object for cleanup, in the WeakRegistry. >> (not on my machine, sorry I cannot put an example, but look around) > > It is simple and here is an example: > > > Create a class: > > Object subclass: #Bar > instanceVariableNames: 'id' > classVariableNames: '' > category: 'Foo' > > implemented an #initialize method > > initialize > super initialize. > id := UUID new. > Transcript show: 'Initialized ', id printString; cr > > and implemented a finalization method: > > finalize > > Transcript show: 'Finalized ', id printString; cr > > Now in the workspace I instantiate the object: > > |anObject| > Transcript open; clear. > anObject := Bar new. > Transcript flush. > WeakRegistry default add: anObject. > > and by forcing garbage collection in a second step I can > see that the finalization method is working: > > 3 timesRepeat: [ Smalltalk garbageCollect ]. > Transcript flush. > > > And I get the following output > > Initialized 4aa47ef1-0e4c-9a47-bddf-b406ee2042e4 > Finalized 4aa47ef1-0e4c-9a47-bddf-b406ee2042e4 > > If it doesnt work check your VM for updates. > > I'm using Pharo4.0 Latest update: #40442 on Windows with the following VM: > Win32 built on Sep 4 2014 01:13:32 Compiler: 4.6.2 VMMaker versionString https://github.com/pharo-project/pharo-vm.git > Commit: c7bc23dd6053d5f9934f7dd427537f76fc96eb32 Jenkins build #14851 > ---> Save our in-boxes! http://emailcharter.org <--- Johan Fabry - http://pleiad.cl/~jfabry PLEIAD lab - Computer Science Department (DCC) - University of Chile |
Hi Johan,
Be careful, it is not the object that will execute the finalizing code but a shallow copy of it. It can lead to deep debugging session sometimes ;-) o := Object new. WeakRegistry default add: o. "a shallow copy of o is registered" o := nil. Smalltalk garbageCollect. "the shallow copy of o will receive the finalize message" Cheers, Luc 2015-01-14 19:13 GMT+01:00 Johan Fabry <[hidden email]>:
|
---> Save our in-boxes! http://emailcharter.org <---
Johan Fabry - http://pleiad.cl/~jfabry PLEIAD lab - Computer Science Department (DCC) - University of Chile |
what if the object stores a reference to itself? then you can access it from the shadow copy? On Thu, Jan 15, 2015 at 4:39 AM, Johan Fabry <[hidden email]> wrote:
|
> On 14 Jan 2015, at 11:29 , Ben Coman <[hidden email]> wrote: > > what if the object stores a reference to itself? then you can access it from the shadow copy? GC notification is triggered *after* objects are removed, so even if that were to work*, it'd be nil at the time the executor got around to being notified. For "about to be" instead of "was just" GC'd, you'd need Ephemerons, not finalization. Removing a class you're an instance of might be a bit fishy as well. (as I understand were to be the case if you only implement #finalize), though it'd be nice with some details why it "didn't work out" for Johan. Working around that would be specifying a custom #executor instead of #finalize, returning an instance of a separate class, with a slot for the class to be removed when triggered. (That executor class would have to implement finalize, of course) Cheers, Henry * The ref would have to be held through a weak array, otherwise the executor would have a strong reference to the object, and it'd never be garbage collected in the first place... Image Roots -> WeakReg -> Executor -> MyObj |
As I’ve been asked, I’ll clarify a bit more. When I said it worked before I was actually wrong because I had forgotten to remove some alternative cleanup code (the alternative works but it’s like using a cannon to kill a fly). This is part of the interpreter for Live Robot Programming that Miguel and I are working on. As part of that we need a data structure that holds scopes, for variables but also for other things. It turns out that for the variables part we can map rather nicely to classes, which gives us a bunch of advantages. So for each scope I generate a class. The scope keeps that class in a ‘vars’ instance variable (there are never any instances of these classes BTW). When the scope is garbage collected I want to remove the class from the system. So I put #finalize in the scope with the idea to remove the class, but it turns out that ‘vars’ is always nil. So in the end it did not work out ... > On Jan 15, 2015, at 15:10, Henrik Johansen <[hidden email]> wrote: > > Removing a class you're an instance of might be a bit fishy as well. (as I understand were to be the case if you only implement #finalize), though it'd be nice with some details why it "didn't work out" for Johan. ---> Save our in-boxes! http://emailcharter.org <--- Johan Fabry - http://pleiad.cl/~jfabry PLEIAD lab - Computer Science Department (DCC) - University of Chile |
> On 16 Jan 2015, at 1:25 , Johan Fabry <[hidden email]> wrote: > > > As I’ve been asked, I’ll clarify a bit more. When I said it worked before I was actually wrong because I had forgotten to remove some alternative cleanup code (the alternative works but it’s like using a cannon to kill a fly). > > This is part of the interpreter for Live Robot Programming that Miguel and I are working on. As part of that we need a data structure that holds scopes, for variables but also for other things. It turns out that for the variables part we can map rather nicely to classes, which gives us a bunch of advantages. So for each scope I generate a class. The scope keeps that class in a ‘vars’ instance variable (there are never any instances of these classes BTW). When the scope is garbage collected I want to remove the class from the system. So I put #finalize in the scope with the idea to remove the class, but it turns out that ‘vars’ is always nil. So in the end it did not work out ... You're probably registering the scope for finalization before setting the vars insvar? The shadow copy is made at the point of registration, so any subsequent assignments to the scope's instvars is not accounted for. Cheers, Henry |
> On Jan 16, 2015, at 12:04, Henrik Johansen <[hidden email]> wrote: > > >> On 16 Jan 2015, at 1:25 , Johan Fabry <[hidden email]> wrote: >> >> >> As I’ve been asked, I’ll clarify a bit more. When I said it worked before I was actually wrong because I had forgotten to remove some alternative cleanup code (the alternative works but it’s like using a cannon to kill a fly). >> >> This is part of the interpreter for Live Robot Programming that Miguel and I are working on. As part of that we need a data structure that holds scopes, for variables but also for other things. It turns out that for the variables part we can map rather nicely to classes, which gives us a bunch of advantages. So for each scope I generate a class. The scope keeps that class in a ‘vars’ instance variable (there are never any instances of these classes BTW). When the scope is garbage collected I want to remove the class from the system. So I put #finalize in the scope with the idea to remove the class, but it turns out that ‘vars’ is always nil. So in the end it did not work out ... > > You're probably registering the scope for finalization before setting the vars insvar? > The shadow copy is made at the point of registration, so any subsequent assignments to the scope's instvars is not accounted for. Yes! Silly me :-/ that was the problem! Thanks for pointing it out! It’s still not perfect: when running the tests +-half of the generated classes are not removed, but maybe the test runner still holds some references. As I said before, I don’t have much time to spend on this … I will need to make some time to investigate more later. ---> Save our in-boxes! http://emailcharter.org <--- Johan Fabry - http://pleiad.cl/~jfabry PLEIAD lab - Computer Science Department (DCC) - University of Chile |
> On 18 Jan 2015, at 17:43, Johan Fabry <[hidden email]> wrote: > >> >> On Jan 16, 2015, at 12:04, Henrik Johansen <[hidden email]> wrote: >> >> >>> On 16 Jan 2015, at 1:25 , Johan Fabry <[hidden email]> wrote: >>> >>> >>> As I’ve been asked, I’ll clarify a bit more. When I said it worked before I was actually wrong because I had forgotten to remove some alternative cleanup code (the alternative works but it’s like using a cannon to kill a fly). >>> >>> This is part of the interpreter for Live Robot Programming that Miguel and I are working on. As part of that we need a data structure that holds scopes, for variables but also for other things. It turns out that for the variables part we can map rather nicely to classes, which gives us a bunch of advantages. So for each scope I generate a class. The scope keeps that class in a ‘vars’ instance variable (there are never any instances of these classes BTW). When the scope is garbage collected I want to remove the class from the system. So I put #finalize in the scope with the idea to remove the class, but it turns out that ‘vars’ is always nil. So in the end it did not work out ... >> >> You're probably registering the scope for finalization before setting the vars insvar? >> The shadow copy is made at the point of registration, so any subsequent assignments to the scope's instvars is not accounted for. > > Yes! Silly me :-/ that was the problem! Thanks for pointing it out! > > It’s still not perfect: when running the tests +-half of the generated classes are not removed, but maybe the test runner still holds some references. As I said before, I don’t have much time to spend on this … I will need to make some time to investigate more later. Johan, I think that is quite normal. It is hard to force GC and thus weak registry and finalisation behaviour. After a while they will probably be gone. I see the same thing with lingering sockets, network connections or worker threads. In the end everything gets cleaned up. If not, you might have a problem ;-) Sven > ---> Save our in-boxes! http://emailcharter.org <--- > > Johan Fabry - http://pleiad.cl/~jfabry > PLEIAD lab - Computer Science Department (DCC) - University of Chile |
Free forum by Nabble | Edit this page |