Sig,

Dumb question: how much does an executor need to know about this?  It can't 
strongly bind the outgoing object or weaklings won't let go and finalization 
will never happen.  Whether the guidance to it is in the form of "clean up" or 
"skip it," it needs to come from the weak registry, finalization framework, or 
whatever you want to call it.  Dolphin handles finalization with support from 
the VM, allowing the outgoing object to do the finalization itself, often in 
the form of releasing external resources, so there is no concept of executor, 
let alone multiple executors.

I have been arguing in favor of thread safety for these mechanisms, and I 
suspect this is another example of why it is needed.  Why would one want more 
than one object ready to destroy an external handle when a single object 
disappears?  The creation of the redundant executors is a recipe for for a 
double free and resulting crash.  I think we should prevent such redundancy, 
and would be readily able to do so if the registries were thread safe giving 
#at:ifAbsentPut: the chops to do the job.

Am I missing something?

Bill



________________________________________
From: [email protected] 
[[email protected]] On Behalf Of Igor Stasenko 
[[email protected]]
Sent: Sunday, October 10, 2010 7:10 PM
To: The general-purpose Squeak developers list
Cc: Pharo Development
Subject: Re: [Pharo-project] [squeak-dev] Re: WeakRegistry>>remove: - when 
you'll be in trouble

On 10 October 2010 23:43, Levente Uzonyi <[email protected]> wrote:
> On Sun, 10 Oct 2010, Igor Stasenko wrote:
>
>> A current implementation of this method
>>
>> remove: oldObject ifAbsent: exceptionBlock
>>        "Remove oldObject as one of the receiver's elements."
>>
>>        oldObject ifNil: [ ^nil ].
>>        ^(self protected: [ valueDictionary removeKey: oldObject ifAbsent:
>> nil ])
>>                ifNil: [ exceptionBlock value ]
>>
>> simply removes a previously registered object from registry and voila.
>>
>> Now lets get back to our discussion about multiple finalizers per
>> object and using them in weak subscriptions etc.
>>
>> Suppose i am added a socket to weak registry,
>> and suppose i am added a weak subscription to it.
>>
>> Now, if i do 'socket close' , it tells weak registry to remove it from
>> list.
>> And what we'll have:
>> - socket handle is closed
>> - socket is wiped from weak registry
>> - but weak subscription still listed somewhere in a list of subscriptions
>>
>>
>> My suggestion is, that upon #remove:,
>> a weak registry should notify all executors that object of interest
>> are no longer takes part in finalization scheme,
>> so they should not count on receiving #finalize eventually.
>>
>> In other words:
>>
>> remove: oldObject ifAbsent: exceptionBlock
>>        "Remove oldObject as one of the receiver's elements."
>>
>>        oldObject ifNil: [ ^nil ].
>>        ^(self protected: [ | executor |
>>            executor := valueDictionary removeKey: oldObject ifAbsent: nil.
>>            executor discardFinalization.
>>        ])
>>        ifNil: [ exceptionBlock value ]
>
> It's only an issue with the new WeakRegistry implementation, previous
> implementations don't have such problem. I think changing the method as you
> suggested, implementing WeakFinalizerItem >> #discardFinalization as
> "executor := nil" and changing WeakFinalizerItem >> #finalizaValues to
> ignore the executor if it's nil will fix the problem. Am I right?
>
> I don't get how "multiple finalizers per object" is related to this problem
> at all.
>

No, you miss the point.
When you removing object from weak registry, it is important , time to
time to tell all of its executors,
that they will no longer receive #finalize, because object is no
longer a member of weak registry.

If you simply set executor := nil, it does nothing, an executor itself
did not notified that he won't be needed
in any possible future.
So, if your finalization action is to remove some object(s) from the
list , you'll get your list dirty after object will die,
because #finalize will be never sent to your executor.

Here the simple test case:

| coll obj someWrapper |
coll := OrderedCollection new.
obj := Object new.
someWrapper := WeakArray with: obj.
coll add: someWrapper.

obj toFinalizeSend: #remove: to: coll with: someWrapper.
obj finalizationRegistry remove: obj.
obj := nil.
Smalltalk garbageCollect.
self assert: coll isEmpty


the point is, that once you doing a #remove: ,
your finalization scheme is broken.

>
> Levente
>

--
Best regards,
Igor Stasenko AKA sig.

_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply via email to