Notification on GC of an object?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Notification on GC of an object?

Torsten Bergmann
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

Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

jfabry

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


Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

Luc Fabresse
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]>:

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



Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

jfabry

Yes, in the end it’s not working out for me, sadly. I think it’s because of that, but I’m not sure as it’s complicated … I’ll show you next week if you want to know more.

On Jan 14, 2015, at 16:14, Luc Fabresse <[hidden email]> wrote:

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]>:

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






---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD lab  -  Computer Science Department (DCC)  -  University of Chile

Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

Ben Coman
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:

Yes, in the end it’s not working out for me, sadly. I think it’s because of that, but I’m not sure as it’s complicated … I’ll show you next week if you want to know more.

On Jan 14, 2015, at 16:14, Luc Fabresse <[hidden email]> wrote:

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]>:

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






---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD lab  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

Henrik Sperre Johansen

> 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


Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

jfabry

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


Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

Henrik Sperre Johansen

> 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
Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

jfabry

> 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


Reply | Threaded
Open this post in threaded view
|

Re: Notification on GC of an object?

Sven Van Caekenberghe-2

> 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