Registry.st
changeset 6439 0f841258ec4a
parent 6421 58dca33cf0fc
child 6468 2c481bb59a0f
equal deleted inserted replaced
6438:9df1edfc0b54 6439:0f841258ec4a
    37 
    37 
    38 documentation
    38 documentation
    39 "
    39 "
    40     Registries provide an easy interface to using WeakArrays. 
    40     Registries provide an easy interface to using WeakArrays. 
    41     A class, which wants to be informed of instance-death, can put a created object
    41     A class, which wants to be informed of instance-death, can put a created object
    42     into a registry. The registry will create a (shallow-)copy of the object, and
    42     into a registry. The registry will create an executor, which is a (shallow-)copy 
    43     watch out for death of the original object. When it dies, the copy will
    43     of the object, and watch out for death of the original object. When it dies, 
    44     be sent a #disposed-message.
    44     the executor will be sent a #finalize message.
    45     The trick with the shallow copy is especially nice, you can think of it as
    45     The trick with the shallow copy is especially nice, you can think of it as
    46     being the original object which died.
    46     being the original object which died.
    47 
    47 
    48     All objects, which keep external resources (such as fileDescriptors, fonts, 
    48     All objects, which keep external resources (such as fileDescriptors, fonts, 
    49     colormap-entries etc.) should be registered, so that the underlying resource
    49     colormap-entries etc.) should be registered, so that the underlying resource
    50     can be freed when the object goes away.
    50     can be freed when the object goes away.
    51 
    51 
    52     Of course, you too can use it to do whatever you need to do in case of the
    52     Of course, you too can use it to do whatever you need to do in case of the
    53     death of an object.
    53     death of an object.
    54 
    54 
    55     Registries use #shallowCopyForFinalization to aquire the copy of the original,
    55     Registries use #executor to aquire the copy of the original,
    56     this can be redefined in registered classes for faster copying 
    56     this can be redefined in registered classes for faster copying 
    57     (typically, not all internal state but only some device handles are needed for 
    57     (typically, not all internal state but only some device handles are needed for 
    58     finalization). I if the to-be-registered object is large, this method may also
    58     finalization). I if the to-be-registered object is large, this method may also
    59     return a stub (placeHolder) object. (i.e. there is no need for the copy to be
    59     return a stub (placeHolder) object. (i.e. there is no need for the copy to be
    60     of the same class as the original, as long as it implements disposed and frees
    60     of the same class as the original, as long as it implements #finalize and frees
    61     the relevant OS resources ...)
    61     the relevant OS resources ...)
    62     Example uses are found in Form, Color, ExternalStream and Font
    62     Example uses are found in Form, Color, ExternalStream and Font
    63 
    63 
    64     [author:]
    64     [author:]
    65         Claus Gittinger
    65         Claus Gittinger
    83 ! !
    83 ! !
    84 
    84 
    85 !Registry methodsFor:'dispose handling'!
    85 !Registry methodsFor:'dispose handling'!
    86 
    86 
    87 informDispose:someHandle
    87 informDispose:someHandle
    88     "send a dispose message - this is sent to the phantom,
    88     "send a dispose message - this is sent to the executor,
    89      since the original is already gone"
    89      since the original is already gone"
    90 
    90 
    91     someHandle disposed
    91     someHandle finalize
    92 
    92 
    93     "Modified: 16.1.1997 / 17:23:46 / cg"
    93     "Modified: 16.1.1997 / 17:23:46 / cg"
    94 !
    94 !
    95 
    95 
    96 update:something with:aParameter from:changedObject
    96 update:something with:aParameter from:changedObject
    97     "an instance has been destroyed - look which one it was"
    97     "an instance has been destroyed - look which one it was"
    98 
    98 
    99     |phantom
    99     |executor
   100      index  "{ Class: SmallInteger }"
   100      index  "{ Class: SmallInteger }"
   101      sz     "{ Class: SmallInteger }"
   101      sz     "{ Class: SmallInteger }"
   102      o myHandleArray wasBlocked|
   102      o myHandleArray wasBlocked|
   103 
   103 
   104     something == #ElementExpired ifTrue:[
   104     something == #ElementExpired ifTrue:[
   111             index := 1.
   111             index := 1.
   112             [index <= sz] whileTrue:[
   112             [index <= sz] whileTrue:[
   113                 o := registeredObjects at:index.
   113                 o := registeredObjects at:index.
   114                 o notNil ifTrue:[
   114                 o notNil ifTrue:[
   115                     o == 0 ifTrue:[
   115                     o == 0 ifTrue:[
   116                         phantom := myHandleArray at:index.
   116                         executor := myHandleArray at:index.
   117                         registeredObjects at:index put:nil.
   117                         registeredObjects at:index put:nil.
   118                         tally := tally - 1.
   118                         tally := tally - 1.
   119                         phantom notNil ifTrue:[
   119                         executor notNil ifTrue:[
   120                             myHandleArray at:index put:nil.
   120                             myHandleArray at:index put:nil.
   121 
   121 
   122                             "/
   122                             "/
   123                             "/ allow interrupts for a while ...
   123                             "/ allow interrupts for a while ...
   124                             "/
   124                             "/
   125                             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   125                             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   126                             self informDispose:phantom.
   126                             self informDispose:executor.
   127                             OperatingSystem blockInterrupts.
   127                             OperatingSystem blockInterrupts.
   128 
   128 
   129                             "/
   129                             "/
   130                             "/ any change in an interrupt or dispose handling ?
   130                             "/ any change in an interrupt or dispose handling ?
   131                             "/
   131                             "/
   176 !Registry methodsFor:'private'!
   176 !Registry methodsFor:'private'!
   177 
   177 
   178 repairTally
   178 repairTally
   179     |sz          "{ Class: SmallInteger }"
   179     |sz          "{ Class: SmallInteger }"
   180      cnt         "{ Class: SmallInteger }"
   180      cnt         "{ Class: SmallInteger }"
   181      phantom wasBlocked|
   181      executor wasBlocked|
   182 
   182 
   183     wasBlocked := OperatingSystem blockInterrupts.
   183     wasBlocked := OperatingSystem blockInterrupts.
   184 
   184 
   185     indexTable := WeakIdentityDictionary new.
   185     indexTable := WeakIdentityDictionary new.
   186 
   186 
   187     sz := registeredObjects size.
   187     sz := registeredObjects size.
   188     cnt := 0.
   188     cnt := 0.
   189 
   189 
   190     1 to:sz do:[:index |
   190     1 to:sz do:[:index |
   191         ((phantom := registeredObjects at:index) notNil 
   191         ((executor := registeredObjects at:index) notNil 
   192         and:[phantom ~~ 0]) ifTrue:[
   192         and:[executor ~~ 0]) ifTrue:[
   193             indexTable at:phantom put:index.
   193             indexTable at:executor put:index.
   194             cnt := cnt + 1.
   194             cnt := cnt + 1.
   195         ] ifFalse:[
   195         ] ifFalse:[
   196             handleArray at:index put:nil.
   196             handleArray at:index put:nil.
   197             registeredObjects at:index put:nil.
   197             registeredObjects at:index put:nil.
   198         ]
   198         ]
   206 resize
   206 resize
   207     |sz          "{ Class: SmallInteger }"
   207     |sz          "{ Class: SmallInteger }"
   208      dstIndex    "{ Class: SmallInteger }"
   208      dstIndex    "{ Class: SmallInteger }"
   209      realNewSize "{ Class: SmallInteger }"
   209      realNewSize "{ Class: SmallInteger }"
   210      newObjects newHandles wasBlocked 
   210      newObjects newHandles wasBlocked 
   211      phantom|
   211      executor|
   212 
   212 
   213     sz := registeredObjects size.
   213     sz := registeredObjects size.
   214 
   214 
   215     (sz > 50 and:[tally < (sz // 2)]) ifTrue:[
   215     (sz > 50 and:[tally < (sz // 2)]) ifTrue:[
   216         "/ shrink
   216         "/ shrink
   223         newHandles := Array new:realNewSize.
   223         newHandles := Array new:realNewSize.
   224         indexTable := WeakIdentityDictionary new.
   224         indexTable := WeakIdentityDictionary new.
   225 
   225 
   226         dstIndex := 1.
   226         dstIndex := 1.
   227         1 to:sz do:[:index |
   227         1 to:sz do:[:index |
   228             (phantom := registeredObjects at:index) notNil ifTrue:[
   228             (executor := registeredObjects at:index) notNil ifTrue:[
   229                 dstIndex > realNewSize ifTrue:[
   229                 dstIndex > realNewSize ifTrue:[
   230                     'Registry [error]: size given is too small in resize' errorPrintCR.
   230                     'Registry [error]: size given is too small in resize' errorPrintCR.
   231                     self repairTally.
   231                     self repairTally.
   232                     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   232                     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   233                     ^ self
   233                     ^ self
   234                 ].
   234                 ].
   235                 newObjects at:dstIndex put:phantom.
   235                 newObjects at:dstIndex put:executor.
   236                 newHandles at:dstIndex put:(handleArray at:index).
   236                 newHandles at:dstIndex put:(handleArray at:index).
   237                 indexTable at:phantom put:dstIndex.
   237                 indexTable at:executor put:dstIndex.
   238 
   238 
   239                 dstIndex := dstIndex + 1
   239                 dstIndex := dstIndex + 1
   240             ]
   240             ]
   241         ].
   241         ].
   242 
   242 
   349             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   349             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   350             ^ self
   350             ^ self
   351         ].
   351         ].
   352 
   352 
   353         "/ mhmh - a registeredObject vanished, but its
   353         "/ mhmh - a registeredObject vanished, but its
   354         "/ phantom is still there ...
   354         "/ executor is still there ...
   355 
   355 
   356         "/
   356         "/
   357         "/ this may happen, if the registries dispose handling is 
   357         "/ this may happen, if the registries dispose handling is 
   358         "/ currently being executed by a lower priority process,
   358         "/ currently being executed by a lower priority process,
   359         "/ and the registeredObject has already been nilled,
   359         "/ and the registeredObject has already been nilled,
   360         "/ but the phantom is being notified (in the other process).
   360         "/ but the executor is being notified (in the other process).
   361 
   361 
   362 "/        'Registry [info]: leftOver phantom: ' infoPrint. p infoPrintCR.
   362 "/        'Registry [info]: leftOver executor: ' infoPrint. p infoPrintCR.
   363 
   363 
   364 "/        "tell the phantom"
   364 "/        "tell the executor"
   365 "/        handleArray at:index put:nil.
   365 "/        handleArray at:index put:nil.
   366 "/        tally := tally - 1.
   366 "/        tally := tally - 1.
   367 "/        self informDispose:p.
   367 "/        self informDispose:p.
   368 "/        p := nil.
   368 "/        p := nil.
   369 
   369 
   395     "Modified: / 7.1.1997 / 16:56:03 / stefan"
   395     "Modified: / 7.1.1997 / 16:56:03 / stefan"
   396     "Modified: / 22.4.1998 / 11:09:23 / cg"
   396     "Modified: / 22.4.1998 / 11:09:23 / cg"
   397 !
   397 !
   398 
   398 
   399 registerChange:anObject
   399 registerChange:anObject
   400     "a registered object has changed, create a new phantom"
   400     "a registered object has changed, create a new executor"
   401 
   401 
   402     |index wasBlocked copy|
   402     |index wasBlocked copy|
   403 
   403 
   404     wasBlocked := OperatingSystem blockInterrupts.
   404     wasBlocked := OperatingSystem blockInterrupts.
   405     registeredObjects isNil ifTrue:[
   405     registeredObjects isNil ifTrue:[
   418 
   418 
   419     "Modified: 6.3.1997 / 22:24:15 / cg"
   419     "Modified: 6.3.1997 / 22:24:15 / cg"
   420 !
   420 !
   421 
   421 
   422 unregister:anObject
   422 unregister:anObject
   423     "remove registration of anObject, without telling the phantom;
   423     "remove registration of anObject, without telling the executor;
   424      should be sent, if we are no more interested in destruction of
   424      should be sent, if we are no more interested in destruction of
   425      anObject (i.e. it no longer holds external resources)."
   425      anObject (i.e. it no longer holds external resources)."
   426 
   426 
   427     |index wasBlocked|
   427     |index wasBlocked|
   428 
   428 
   471 ! !
   471 ! !
   472 
   472 
   473 !Registry class methodsFor:'documentation'!
   473 !Registry class methodsFor:'documentation'!
   474 
   474 
   475 version
   475 version
   476     ^ '$Header: /cvs/stx/stx/libbasic/Registry.st,v 1.55 2002-02-26 13:00:48 cg Exp $'
   476     ^ '$Header: /cvs/stx/stx/libbasic/Registry.st,v 1.56 2002-03-04 14:20:19 stefan Exp $'
   477 ! !
   477 ! !