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
