ValueHolderWithWeakDependents.st
author ca
Sat, 26 Oct 2002 17:46:27 +0200
changeset 1651 429e02e097d9
parent 1557 e5e78ee63670
child 1803 d69cb54a3b56
permissions -rw-r--r--
can now specify if menu action is to be performed by originating widget (instead of application)

"{ Package: 'stx:libview2' }"

ValueHolder subclass:#ValueHolderWithWeakDependents
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Support-Models'
!


!ValueHolderWithWeakDependents methodsFor:'dependents access'!

addDependent:anObject
    "make the argument, anObject be a weak dependent of the receiver"

    |wasBlocked|

    wasBlocked := OperatingSystem blockInterrupts.
    [
        |deps dep|

        deps := dependents.
        "/
        "/ store the very first dependent directly in
        "/ the dependents instVar
        "/
        (deps isNil and:[anObject isCollection not]) ifTrue:[
            dependents := WeakArray with:anObject
        ] ifFalse:[
            deps class == WeakArray ifTrue:[
                dep := deps at:1.
                dep ~~ anObject ifTrue:[
                    (dep isNil or:[dep == 0]) ifTrue:[
                        deps at:1 put:anObject
                    ] ifFalse:[
                        self dependents:(WeakIdentitySet with:dep with:anObject)
                    ]
                ]
            ] ifFalse:[
                deps add:anObject
            ]
        ]
    ] ensure:[
        wasBlocked ifFalse:[
            OperatingSystem unblockInterrupts
        ]
    ]

    "Modified: 8.1.1997 / 23:40:30 / cg"
!

dependentsDo:aBlock
    "evaluate aBlock for all of my dependents"

    |deps|

    deps := dependents.
    deps size ~~ 0 ifTrue:[
        deps do:[:d | 
                    (d notNil and:[d ~~ 0]) ifTrue:[
                        aBlock value:d
                    ]
                ]
    ].

!

removeDependent:anObject
    "make the argument, anObject be independent of the receiver"

    |wasBlocked|

    "/ must do this save from interrupts, since the dependents collection
    "/ is possibly accessed from multiple threads.
    "/ Used to use #valueUninterruptably here; inlined that code for slightly
    "/ faster execution.

    wasBlocked := OperatingSystem blockInterrupts.
    [
        |deps n d|

        deps := dependents.
        deps size ~~ 0 ifTrue:[

            "/ to save a fair amount of memory in case of
            "/ many dependencies, we store a single dependent in
            "/ a WeakArray, and switch to a WeakSet if more dependents are
            "/ added. Here we have to do the inverse ...

            deps class == WeakArray ifTrue:[
                ((d := deps at:1) == anObject 
                or:[d isNil
                or:[d == 0]]) ifTrue:[
                    dependents := nil
                ]
            ] ifFalse:[
                deps remove:anObject ifAbsent:[].
                (n := deps size) == 0 ifTrue:[
                    dependents := nil
                ] ifFalse:[
                    n == 1 ifTrue:[
                        d := deps firstIfEmpty:nil.
                        d notNil ifTrue:[
                            deps := WeakArray with:d
                        ] ifFalse:[
                            deps := nil
                        ].
                        dependents := deps.
                    ]
                ]
            ]
        ]
    ] ensure:[
        wasBlocked ifFalse:[
            OperatingSystem unblockInterrupts
        ]
    ]

    "Modified: / 26.1.1998 / 19:51:50 / cg"
! !

!ValueHolderWithWeakDependents class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libview2/ValueHolderWithWeakDependents.st,v 1.2 2002-02-26 12:59:22 cg Exp $'
! !