Documentation of class 'WeakArray':
Object | +--Collection | +--SequenceableCollection | +--ArrayedCollection | +--WeakArray
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)
WeakArray handling adds small some overhead to the VM (each weakarray is scanned after each GC). It is uncertain, if the current mechanism works well with (say) ten-thousands of weakArrays. We had the system running with >2000 weakArrays, some being quite big for a while and had a few percent of added gc time. The system as delivered creates between 50 and 100 weakArrays, but with many dependents, this number may grow. If you need the dependency mechanism on a huge number of objects, consider adding a (non-weak) dependents field to your class - take the implementation of Model as a guide (or subclass them from Model).
Array WeakIdentitySet WeakIdentityDictionary Registry Model
Instance protocol:GC registration
ST/X 22.214.171.124; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Tue, 28 Mar 2023 06:02:05 GMT