|
Class: WeakArray
Object
|
+--Collection
|
+--SequenceableCollection
|
+--ArrayedCollection
|
+--WeakArray
- Package:
- stx:libbasic
- Category:
- Collections-Weak
- Version:
- rev:
1.108
date: 2023/10/06 11:54:48
- user: stefan
- file: WeakArray.st directory: libbasic
- module: stx stc-classLibrary: libbasic
WeakArrays can be used to trace disposal of objects; in contrast to other
objects, references by WeakArrays will NOT keep an object from being
garbage collected.
Instead, whenever an object kept in a WeakArray dies, its entry is set to a SmallInteger,
and the WeakArray is informed by the storage manager. The WeakArray itself
then informs possible dependents via the dependency mechanism.
WeakArrays are used to track disposal of objects which keep external
world resources. For example, FileStreams must close their underlying
file when disposed (otherwise you could run out of OS filedescriptors).
This can be done by keeping the FileStream objects in a weakArray, and
keep a parallel array of filedescriptors. Whenever a fileStream is
freed, search both arrays for an index where the stream is set to a SmallInteger, but the
filedescriptor is non-nil. Then close that file, and nil the filedescriptor
entry. Notice, that there is a class (Registry) which does exactly this in
a more programmer friendly way.
Another application is caching of data: keep it in a weakArray, so the
data in that cache will not be unreclaimable due to being cached.
(for example, the ResourcePack class uses a WeakArray to cache recently
used resource data for a while).
The way in which weakArrays get informed by the runtime system is via
an interrupt (DisposeInterrupt) which is first sent to the disposeHandler
(typically ObjectMemory). ObjectMemory then takes the required steps to
notify all weakArrays via the #lostPointer message.
The reason for not sending messages directly from the VM is to make it
possible to run the finalization code at lower priority or from another class.
Also, as a side effect, it is possible to delay finalization by blocking
interrupts. (thus, the actual sending of the #lostPointer message is under
control of Smalltalk code, which is modifyable).
A weakArray notifies its dependents via normal dependency notfications.
As a possible option, we could perform the weakArray scanning only in
the oldSpace reclamation code - this would remove most of the overhead,
but will lead to much longer delayed finalization .... we will see.
[instance variables:]
dependents get informed via #change notifiction
that the weakArray has lost pointers.
Having the dependents here is an optimization.
[class variables:]
RegistrationFailedSignal raised if a weakArray cannot be
registered by the VM. This only happens,
if the VM has to resize its internal tables
and is running out of malloc-memory.
[memory requirements:]
OBJ-HEADER + (size * ptr-size) + ptr-size
+ sizeof(dependents-collection)
copyrightCOPYRIGHT (c) 1991 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
initialization
-
initialize
-
adjust my class flags and setup the private signal
instance creation
-
basicNew: size
-
return a new weakArray with size slots
queries
-
isBuiltInClass
-
return true if this class is known by the run-time-system.
Here, true is returned for myself, false for subclasses.
GC registration
-
registerAsWeakArray
-
register the receiver in the VM -
i.e. tell the VM to nil disposed entries in the receiver
and notify the disposeInterruptHandler whenever that happened.
accessing
-
at: index ifAbsent: exceptionValue
-
return the indexed instance variable with index, anInteger,
or exceptionValue if the index is invalid.
-
at: index ifInvalid: exceptionalValue
-
return the indexed instance variable with index, anInteger,
but only if still valid; otherwise return the value from exceptionalValue
-
basicAt: index
-
return the indexed instance variable with index, anInteger.
Reimplemented here for IGC readBarrier.
(You don't have to understand this.)
-
basicAt: index put: someObject
-
store someObject in the weakArray at some index.
-
validElements
-
answer all of my values that are neither garbage collected nor nil as an Array
add
-
addAllTo: aCollection
-
add all elements of the receiver that are still valid to aCollection.
Return aCollection.
Redefined here to exclude outdated elements.
copying
-
skipInstvarIndexInDeepCopy: index
-
a helper for deepCopy; only indices for which this method returns
false are copied in a deep copy.
copying-private
-
postCopy
-
the copy does not share dependencies
-
postCopyFrom: original
-
the copy does not share dependencies
-
postDeepCopy
-
the copy does not share dependencies
dependents access
-
addDependent: anObject
-
make the argument, anObject be a dependent of the receiver
-
dependents
-
return the dependents of the receiver.
-
dependents: aCollectionOrNil
-
set the dependents of the receiver
-
dependentsDo: aBlock
-
evaluate aBlock for all of my dependents
-
removeDependent: anObject
-
make the argument, anObject be independent of the receiver
enumerating
-
do: aBlock
-
evaluate the argument, aBlock for each (living) element in the collection.
- reimplemented for IGC readBarrier.
You don't have to understand this.
-
forAllDeadIndicesDo: aBlock replacingCorpsesWith: newValue
-
evaluate the argument, aBlock for all indices where elements have been
replaced by a SmallInteger (due to a collected object), and replace the element
with newValue.
In the current implementation, the block sees the newValue (i.e. it is
changed before the block is called); this behavior is not guaranteed
with future versions.
Be aware, that while indices are being enumerated, other
slots may change iff the garbage collector finds new garbage.
-
keysAndValuesDo: aBlock
-
evaluate the argument, aBlock for each element in the collection.
- reimplemented for speed.
You don't have to understand this.
-
nonNilElementsDo: aBlock
-
evaluate the argument, aBlock for each non-nil element (treats evacuated values as nil)
-
replaceCorpsesWith: newValue
-
replace all indices where elements have been replaced by a SmallInteger
(due to a collected object), with newValue.
Answer the index of the last entry that is nil or has been nilled, or 0 if there is none.
Be aware, that while indices are being enumerated, other
slots may change iff the garbage collector finds new garbage.
-
validElementsDo: aBlock
-
evaluate the argument, aBlock for each non-nil/non-evacuated element
notification
-
lostPointer
-
I lost a pointer; tell dependents.
This is sent from the finalization code in ObjectMemory.
testing
-
hasValidElements
-
answer true, if i contain at least one element that is neither nil nor garbage collected
-
isWeak
-
return true if the receiver has weak references to its elements.
-
isWeakCollection
-
return true, if the receiver has weak references to its elements.
|