DependentsArray size how does it work ?

nicolas cellier ncellier at ifrance.com
Wed Feb 8 20:17:30 UTC 2006


Le Mercredi 08 Février 2006 14:32, vous avez écrit :
> > I will try it this evening. if not redefined, then the whole class  
> > seems
> > dangerous to me and there might be other side effects.
>
> It gets interesting when you look at the real users of DependArray. The
> only place is
>
> Array>>copyWithDependent: newElement
>         self size = 0 ifTrue:[^DependentsArray with: newElement].
>         ^self copyWith: newElement
>
>
> not directly obvious way of doing it, either: lazy convertion of empty
> arrays, with the place where the real instanciation should have  
> happended
> nicely hidden...
>
>         Marcus

Good evening Marcus,

I will try to focus on real bugs rather than theoretical ones if i can.

I am simply browsing the 33 senders of #dependents  in a 3.8 image.
they will use #myDependents wich will use DependentsArray.

And after 15 minutes, i think i have a clue for potential bug.

Object>>hasUnacceptedEdits
    "Answer true if any of the views on this object has unaccepted edits."

    self dependents
        do: [:each | each hasUnacceptedEdits ifTrue: [^ true]]
        without: self.
    ^ false

does call #do:without: wich is not implemented with a #do: loop but rather (1 
to: self size do:).

SequenceableCollection>>do: aBlock without: anItem
    "Enumerate all elements in the receiver.
    Execute aBlock for those elements that are not equal to the given item"
    "Refer to the comment in Collection|do:."
    1 to: self size do:
        [:index | anItem = (self at: index) ifFalse:[aBlock value: (self at: 
index)]]

If one ever nil a slot (remove a dependent), then there will be harmless 
effects in appearance because (nil hasUnacceptedEdits) will fall back in 
Object>>hasUnacceptedEdits and return false without entering an infinite loop 
since nil has no dependent.

But then, execution will stop at self size, and some real dependents
won't have a chance to tell it hasUnacceptedEdits...

I do not know what are the consequences (a window might close without saving?) 
and i can not exhibit a failure case so the bug is still theoretical.
Maybe there are not many cases when you simply remove a dependent without 
adding a new one, and adding a new one will create a copy of myDependents, in 
this case the bug won't occur, because copy eliminate the nil.

So do you see the possible side effects i were speaking of ?

We should be able to construct a failing code.
Maybe have to search buglist and mailing list to check if someone ever 
experienced something similar...

The same potential problem exist with these ones:

SystemWindow>>replacePane: oldPane with: newPane
    "Make newPane exactly occupy the position and extent of oldPane"

    | aLayoutFrame hadDep |
    hadDep := model dependents includes: oldPane.
etc...

because includes will fall back to (1 to: self size do:) again...

and also in:
TestRunner>>installProgressWatcher
    | win host |
    win := self dependents first.
    ...
This one should rather open an exception i think.

What is the cure ?
I do not know, losely implement in DependentsArray all these collection 
messages that are implemented using (1 to: self size do:) above.
At least #do:without: , #indexOf:startingAt:ifAbsent:, #first, maybe more...

If someone ever change some implementation in a collection superclass (i do 
not know why, efficiency ?), or some one use a new message to act on 
dependents, then same problem will arise again and will be hard to discover 
and to fix (if it silently close your window without exception...).

We should find a better fix than patch i propose above...




More information about the Squeak-dev mailing list