CachingRegistry.st
author Jan Vrany <jan.vrany@labware.com>
Thu, 25 Mar 2021 20:30:03 +0000
branchjv
changeset 25411 248600ba8fd9
parent 23547 c69c97cec351
permissions -rw-r--r--
Fix unlikely but possible race in `WeakValueDictionary` It may happen that value in `valueArray` could have been already collected by the GC but #clearDeadSlots have not yet been called. When this happened, `#at:ifAbsentPut:` returned tombstone rather than updating the dictionary with value from block. This commit fixes this by checking whether `valueArray` contain the tombstone and if so, clearing up the dead slots and restarting the operation. HTH.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     1
"
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     2
 COPYRIGHT (c) 1999 by eXept Software AG
18249
7d686f203624 oops package def was missing
Claus Gittinger <cg@exept.de>
parents: 4434
diff changeset
     3
	      All Rights Reserved
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     4
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     5
 This software is furnished under a license and may be used
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     6
 only in accordance with the terms of that license and with the
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     7
 inclusion of the above copyright notice.   This software may not
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     8
 be provided or otherwise made available to, or used by, any
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     9
 other person.  No title to or ownership of the software is
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    10
 hereby transferred.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    11
"
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
    12
"{ Package: 'stx:libbasic' }"
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    13
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
    14
"{ NameSpace: Smalltalk }"
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    15
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    16
Registry subclass:#CachingRegistry
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    17
	instanceVariableNames:'keptReferences cacheSize'
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    18
	classVariableNames:''
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    19
	poolDictionaries:''
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    20
	category:'System-Support'
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    21
!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    22
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    23
!CachingRegistry class methodsFor:'documentation'!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    24
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    25
copyright
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    26
"
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    27
 COPYRIGHT (c) 1999 by eXept Software AG
18249
7d686f203624 oops package def was missing
Claus Gittinger <cg@exept.de>
parents: 4434
diff changeset
    28
	      All Rights Reserved
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    29
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    30
 This software is furnished under a license and may be used
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    31
 only in accordance with the terms of that license and with the
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    32
 inclusion of the above copyright notice.   This software may not
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    33
 be provided or otherwise made available to, or used by, any
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    34
 other person.  No title to or ownership of the software is
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    35
 hereby transferred.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    36
"
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    37
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    38
!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    39
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    40
documentation
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    41
"
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    42
    A CachingRegistry behaves generally like a registry;
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    43
    However, it keeps hard references to the last n registered objects,
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    44
    preventing them from being garbage collected (and finalized).
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    45
    This is useful for resources, which do not cost too much memory,
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
    46
    but are expensive to allocate - a special candidate of this kind are
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    47
    XFonts. With a CachingRegistry, fonts are kept a bit longer alive
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    48
    and can therefore often be reused - even if temporarily unreferenced.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    49
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    50
    This is kind of experimental.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    51
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    52
    [author:]
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
    53
        Claus Gittinger (cg@exept)
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    54
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    55
    [see also:]
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    56
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    57
    [instance variables:]
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
    58
        keptObjects             Collection      hard referenced objects
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
    59
        cacheSize               Integer         number of hard references
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    60
"
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    61
! !
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    62
20393
4d74f02d1a9f #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20388
diff changeset
    63
!CachingRegistry class methodsFor:'instance creation'!
4d74f02d1a9f #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20388
diff changeset
    64
4d74f02d1a9f #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20388
diff changeset
    65
new:cacheSize
20394
b76075273e88 #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20393
diff changeset
    66
    ^ (super new:cacheSize) cacheSize:cacheSize
20393
4d74f02d1a9f #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20388
diff changeset
    67
! !
4d74f02d1a9f #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20388
diff changeset
    68
20388
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
    69
!CachingRegistry methodsFor:'enumerating'!
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
    70
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
    71
detect:aBlock ifNone:exceptionValue
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
    72
    "... additionaly move it to the front of the LRU chain"
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
    73
20401
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    74
    |cnt|
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    75
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    76
    "first a quick lookup 
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    77
     (most recent entry is at the end, because #removeIdentical makes room at the end)..."
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    78
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    79
    cnt := 1.
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    80
    keptReferences reverseDo:[:obj|
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    81
        (aBlock value:obj) ifTrue:[
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    82
            "if not at the end, put it to the end.
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    83
             but avoid to much remove/add actions"
20435
54505346a337 #OTHER by stefan
Stefan Vogel <sv@exept.de>
parents: 20401
diff changeset
    84
            cnt > (cacheSize // 4) ifTrue:[
20401
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    85
                keptReferences removeIdentical:obj ifAbsent:[].
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    86
                keptReferences addLast:obj.
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    87
            ].
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    88
            ^ obj
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    89
        ].
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    90
        cnt := cnt + 1.
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    91
    ].
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    92
fb5b39df9894 #TUNING by stefan
Stefan Vogel <sv@exept.de>
parents: 20395
diff changeset
    93
    "check the whole registry..."
20994
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
    94
    keyArray validElementsDo:[:eachElement |
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
    95
        eachElement ~~ DeletedEntry ifTrue:[
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
    96
            |realObject|
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
    97
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
    98
            realObject := eachElement.
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
    99
            eachElement == NilEntry ifTrue:[realObject := nil].
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
   100
            (aBlock value:realObject) ifTrue:[
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
   101
                keptReferences size >= cacheSize ifTrue:[
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
   102
                    keptReferences removeFirst.
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
   103
                ].
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
   104
                keptReferences addLast:realObject.
a210e2fb2993 #BUGFIX by stefan
Stefan Vogel <sv@exept.de>
parents: 20630
diff changeset
   105
                ^ realObject
20395
50417882857e #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20394
diff changeset
   106
            ].
20388
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
   107
        ].
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
   108
    ].
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
   109
    ^ exceptionValue value
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
   110
! !
db4b243d97ce #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20043
diff changeset
   111
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   112
!CachingRegistry methodsFor:'private'!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   113
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   114
cacheSize:aNumber
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   115
    keptReferences := OrderedCollection new:aNumber.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   116
    cacheSize := aNumber.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   117
! !
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   118
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   119
!CachingRegistry methodsFor:'registering objects'!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   120
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   121
register:anObject as:aHandle
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   122
    keptReferences removeIdentical:anObject ifAbsent:nil.
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   123
    aHandle notNil ifTrue:[
20395
50417882857e #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20394
diff changeset
   124
        keptReferences size >= cacheSize ifTrue:[
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   125
            keptReferences removeFirst.
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   126
        ].
20395
50417882857e #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 20394
diff changeset
   127
        keptReferences addLast:anObject.
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   128
    ].
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   129
    super register:anObject as:aHandle.
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   130
!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   131
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   132
removeKey:anObject ifAbsent:absentBlock
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   133
    keptReferences removeIdentical:anObject ifAbsent:nil.
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   134
    super removeKey:anObject ifAbsent:absentBlock.
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   135
!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   136
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   137
safeRemoveKey:anObject
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   138
    keptReferences removeIdentical:anObject ifAbsent:nil.
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   139
    super safeRemoveKey:anObject.
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   140
! !
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   141
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   142
!CachingRegistry class methodsFor:'documentation'!
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   143
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   144
version
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   145
    ^ '$Header$'
20394
b76075273e88 #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20393
diff changeset
   146
!
b76075273e88 #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20393
diff changeset
   147
b76075273e88 #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20393
diff changeset
   148
version_CVS
b76075273e88 #FEATURE by stefan
Stefan Vogel <sv@exept.de>
parents: 20393
diff changeset
   149
    ^ '$Header$'
20577
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 20398 20395
diff changeset
   150
!
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 20398 20395
diff changeset
   151
17865
598963c6ff8e Recommited from itself
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 17846
diff changeset
   152
version_SVN
17911
a99f15c5efa5 Updated with /trunk
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 17910
diff changeset
   153
    ^ '$Id: CachingRegistry.st 10761 2012-01-19 11:46:00Z vranyj1 $'
4434
887b60637a1c initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   154
! !
20043
0be0ccf00b36 #REFACTORING by stefan
Stefan Vogel <sv@exept.de>
parents: 18249
diff changeset
   155
17910
8d796ca8bd1d Merged with /trunk
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 17892
diff changeset
   156
17911
a99f15c5efa5 Updated with /trunk
Jan Vrany <jan.vrany@fit.cvut.cz>
parents: 17910
diff changeset
   157