[squeak-dev] The Trunk: System-fbs.581.mcz

commits at source.squeak.org commits at source.squeak.org
Tue Aug 6 21:12:43 UTC 2013


Frank Shearar uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-fbs.581.mcz

==================== Summary ====================

Name: System-fbs.581
Author: fbs
Time: 6 August 2013, 10:12:10.029 pm
UUID: cc68c4e8-144f-b445-9b44-6541c4ead09c
Ancestors: System-fbs.580

Consolidate all finalization stuff in System-Finalization.

=============== Diff against System-fbs.580 ===============

Item was changed:
  SystemOrganization addCategory: #'System-Applications'!
  SystemOrganization addCategory: #'System-Change Notification'!
  SystemOrganization addCategory: #'System-Changes'!
  SystemOrganization addCategory: #'System-Digital Signatures'!
  SystemOrganization addCategory: #'System-Download'!
+ SystemOrganization addCategory: #'System-Exceptions'!
  SystemOrganization addCategory: #'System-FilePackage'!
  SystemOrganization addCategory: #'System-FileRegistry'!
  SystemOrganization addCategory: #'System-Finalization'!
  SystemOrganization addCategory: #'System-Localization'!
  SystemOrganization addCategory: #'System-Object Events'!
  SystemOrganization addCategory: #'System-Object Storage'!
  SystemOrganization addCategory: #'System-Pools'!
  SystemOrganization addCategory: #'System-Preferences'!
  SystemOrganization addCategory: #'System-Serial Port'!
  SystemOrganization addCategory: #'System-Support'!
  SystemOrganization addCategory: #'System-Tools'!
- SystemOrganization addCategory: #'System-Exceptions'!

Item was added:
+ ----- Method: Object>>actAsExecutor (in category '*System-Finalization') -----
+ actAsExecutor
+ 	"Prepare the receiver to act as executor for any resources associated with it"
+ 	self breakDependents!

Item was added:
+ ----- Method: Object>>executor (in category '*System-Finalization') -----
+ executor
+ 	"Return an object which can act as executor for finalization of the receiver"
+ 	^self shallowCopy actAsExecutor!

Item was added:
+ ----- Method: Object>>finalizationRegistry (in category '*System-Finalization') -----
+ finalizationRegistry
+ 	"Answer the finalization registry associated with the receiver."
+ 	^WeakRegistry default!

Item was added:
+ ----- Method: Object>>finalize (in category '*System-Finalization') -----
+ finalize
+ 	"Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority."!

Item was added:
+ ----- Method: Object>>hasMultipleExecutors (in category '*System-Finalization') -----
+ hasMultipleExecutors
+ 	"All objects, except ObjectFinalizerCollection instances should answer false to this message"
+ 	^ false!

Item was added:
+ ----- Method: Object>>retryWithGC:until: (in category '*System-Finalization') -----
+ retryWithGC: execBlock until: testBlock
+ 	"Retry execBlock as long as testBlock returns false. Do an incremental GC after the first try, a full GC after the second try."
+ 	| blockValue |
+ 	blockValue := execBlock value.
+ 	(testBlock value: blockValue) ifTrue:[^blockValue].
+ 	Smalltalk garbageCollectMost.
+ 	blockValue := execBlock value.
+ 	(testBlock value: blockValue) ifTrue:[^blockValue].
+ 	Smalltalk garbageCollect.
+ 	^execBlock value.!

Item was added:
+ ----- Method: Object>>toFinalizeSend:to:with: (in category '*System-Finalization') -----
+ toFinalizeSend: aSelector to: aFinalizer with: aResourceHandle
+ 	"When I am finalized (e.g., garbage collected) close the associated resource handle by sending aSelector to the appropriate finalizer (the guy who knows how to get rid of the resource).
+ 	WARNING: Neither the finalizer nor the resource handle are allowed to reference me. If they do, then I will NEVER be garbage collected. Since this cannot be validated here, it is up to the client to make sure this invariant is not broken."
+ 	self == aFinalizer ifTrue:[self error: 'I cannot finalize myself'].
+ 	self == aResourceHandle ifTrue:[self error: 'I cannot finalize myself'].
+ 	^self finalizationRegistry add: self executor:
+ 		(ObjectFinalizer
+ 			receiver: aFinalizer
+ 			selector: aSelector
+ 			argument: aResourceHandle)!

Item was added:
+ ----- Method: WeakArray class>>finalizationProcess (in category '*System-Finalization') -----
+ finalizationProcess
+ 
+ 	| initialized |
+ 	initialized := false.
+ 	[FinalizationSemaphore wait.
+ 	initialized ifFalse: ["check VM capability once at image startup time"
+ 		WeakFinalizationList initTestPair.
+ 		Smalltalk garbageCollect.
+ 		WeakFinalizationList checkTestPair.
+ 		initialized := true].
+ 	FinalizationLock critical:
+ 		[FinalizationDependents do:
+ 			[ :weakDependent |
+ 			weakDependent ifNotNil:
+ 				[weakDependent finalizeValues]]]
+ 		ifError:
+ 		[:msg :rcvr | rcvr error: msg]] repeat!

Item was added:
+ Object subclass: #WeakFinalizationList
+ 	instanceVariableNames: 'first'
+ 	classVariableNames: 'HasNewFinalization TestItem TestList'
+ 	poolDictionaries: ''
+ 	category: 'System-Finalization'!
+ 
+ !WeakFinalizationList commentStamp: 'Igor.Stasenko 9/22/2010 21:09' prior: 0!
+ IMPORTANT!!!!!!
+ 
+ This class is a special object, recognized by VM.
+ Its only purpose is to 
+ a) identify a special kind of objects who usually having a weak references but
+   also having an instance of me held by first non-weak fixed slot (instance variable).
+ 
+ b) a 'first' instance variable points to the head of a list of items, reported by VM which has weak references which became garbage during last garbage collection
+ 
+ At my class side, there are some public behavior, which is used by finalization process to detect if VM supports new finalization scheme or should use the old one.
+ Weak registry using #hasNewFinalization for switching to correct finalization logic,
+ depending on VM it currently runs on.
+ !

Item was added:
+ ----- Method: WeakFinalizationList class>>checkTestPair (in category 'vm capability test') -----
+ checkTestPair
+ 	HasNewFinalization := TestList swapWithNil notNil.!

Item was added:
+ ----- Method: WeakFinalizationList class>>hasNewFinalization (in category 'vm capability test') -----
+ hasNewFinalization
+ 	^ HasNewFinalization == true!

Item was added:
+ ----- Method: WeakFinalizationList class>>initTestPair (in category 'vm capability test') -----
+ initTestPair
+ 	TestItem := WeakFinalizerItem new list: TestList object: Object new.
+ !

Item was added:
+ ----- Method: WeakFinalizationList class>>initialize (in category 'class initialization') -----
+ initialize
+ 	TestList := self new.!

Item was added:
+ ----- Method: WeakFinalizationList>>first (in category 'accessing') -----
+ first
+ 	^ first!

Item was added:
+ ----- Method: WeakFinalizationList>>swapWithNil (in category 'accessing') -----
+ swapWithNil
+ 
+ 	| head |
+ 	head := first.
+ 	first := nil.
+ 	^ head!

Item was added:
+ Object weakSubclass: #WeakFinalizerItem
+ 	instanceVariableNames: 'list next executor'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'System-Finalization'!
+ 
+ !WeakFinalizerItem commentStamp: 'Igor.Stasenko 9/22/2010 20:59' prior: 0!
+ My instances is used by weak registry to hold a single weak reference
+ and executor(s).
+ 
+ Once object, referenced weakly by my instance become garbage, a weak registry triggers its execution
+ by sending #finalizeValues to my instance.
+ 
+ Note, that a new VM finalization scheme does not implies to use this particular class
+ in order to implement finalization scheme. VM refers only to WeakFinalizationList class. 
+ 
+ In this way, my class and its implementation can serve as an example for implementing various finalization actions, which may differ from this one, provided by default for use by weak registry.
+ 
+ Once initialized, my instance should:
+  - point to particular list (an instance of WeakFinalizationList),
+  - next should be nil
+  - executor or multiple executors initialized
+  - weak reference slot should point to some object of interest
+ 
+ At the moment, when object, referenced weakly, become garbage, VM checks if its fist instance variable is an instance of WeakFinalizationList.
+ If it so, then it adds a given object to this list, and also links the tail of list through 'next' instance variable. 
+ 
+ So, as a result of garbage collection, a list will contain all objects, which had weak references to garbage collected objects. 
+ It is a responsibility of application to manage the instances of WeakFinalizationList's , as well as clear this list before the next garbage collection.
+ As a consequence of that you can:
+  - use multiple different lists and manage them differently in order to react differently when some objects became garbage
+  - you are not obliged to handle/clear the list(s) immediately after GC. You can clean up them periodically.
+  - you can implement own kind of weak referencing object(s), which could use same finalization, provided by newer VMs.
+ 
+ VM requires only that an object with weak reference having at least two instance variables,
+ and its first instance variable points to instance of WeakFinalizationList. Everything else is optional.
+ !

Item was added:
+ ----- Method: WeakFinalizerItem class>>new (in category 'as yet unclassified') -----
+ new
+ 	^ self basicNew: 1!

Item was added:
+ ----- Method: WeakFinalizerItem>>add: (in category 'accessing') -----
+ add: newExecutor
+ 
+ 	executor 
+ 		ifNil: [ executor := newExecutor ]
+ 		ifNotNil: [
+ 			executor hasMultipleExecutors
+ 				ifTrue: [ executor add: newExecutor]
+ 				ifFalse: [ executor := ObjectFinalizerCollection with: executor with: newExecutor ]
+ 		]!

Item was added:
+ ----- Method: WeakFinalizerItem>>clear (in category 'accessing') -----
+ clear
+ 	list := next := nil.!

Item was added:
+ ----- Method: WeakFinalizerItem>>copyWithList: (in category 'copying') -----
+ copyWithList: aList
+ 
+ 	^ self copy list: aList!

Item was added:
+ ----- Method: WeakFinalizerItem>>executor (in category 'accessing') -----
+ executor
+ 	^ executor!

Item was added:
+ ----- Method: WeakFinalizerItem>>finalizeValues (in category 'finalizing') -----
+ finalizeValues
+ 	" cleanup the receiver, so it could be reused "
+ 	| ex |
+ 	ex := executor.
+ 	executor := nil.
+ 	next := nil.
+ 	ex finalize.!

Item was added:
+ ----- Method: WeakFinalizerItem>>list (in category 'accessing') -----
+ list
+ 	^ list!

Item was added:
+ ----- Method: WeakFinalizerItem>>list: (in category 'accessing') -----
+ list: aList
+ 	list := aList!

Item was added:
+ ----- Method: WeakFinalizerItem>>list:object: (in category 'initialize-release') -----
+ list: weakFinalizationList object: anObject
+ 	self assert: (weakFinalizationList class == WeakFinalizationList).
+ 	list := weakFinalizationList.
+ 	self at: 1 put: anObject.
+ !

Item was added:
+ ----- Method: WeakFinalizerItem>>list:object:executor: (in category 'initialize-release') -----
+ list: weakFinalizationList object: anObject executor: anExecutor
+ 	self assert: (weakFinalizationList class == WeakFinalizationList).
+ 	list := weakFinalizationList.
+ 	self at: 1 put: anObject.
+ 	executor := anExecutor!

Item was added:
+ ----- Method: WeakFinalizerItem>>next (in category 'accessing') -----
+ next
+ 	^ next!

Item was added:
+ ----- Method: WeakFinalizerItem>>object (in category 'accessing') -----
+ object
+ 	^ self at: 1!

Item was added:
+ ----- Method: WeakFinalizerItem>>postCopy (in category 'copying') -----
+ postCopy
+ 	executor hasMultipleExecutors ifTrue: [ executor := executor copy ].!

Item was added:
+ Collection subclass: #WeakRegistry
+ 	instanceVariableNames: 'list valueDictionary sema executors'
+ 	classVariableNames: 'Default'
+ 	poolDictionaries: ''
+ 	category: 'System-Finalization'!
+ 
+ !WeakRegistry commentStamp: 'ul 9/26/2010 02:51' prior: 0!
+ I am a registry for objects needing finalization. When an object is added the object as well as its executor is stored. When the object is garbage collected, the executor can take the appropriate action for any resources associated with the object.
+ 
+ This kind of WeakRegistry is using a new VM feature, which allows a more robust finalization support. In contrast to the old implementation, it doesn't spend linear time checking which elements became garbage.
+ 
+ See also:
+ 	Object executor
+ 	Object actAsExecutor
+ 	Object finalize!

Item was added:
+ ----- Method: WeakRegistry class>>default (in category 'accessing') -----
+ default
+ 	^Default ifNil:[Default := self new]!

Item was added:
+ ----- Method: WeakRegistry class>>new (in category 'instance creation') -----
+ new
+ 	| registry |
+ 	registry := super new.
+ 	WeakArray addWeakDependent: registry.
+ 	^registry
+ !

Item was added:
+ ----- Method: WeakRegistry class>>new: (in category 'instance creation') -----
+ new: n
+ 	^ self new!

Item was added:
+ ----- Method: WeakRegistry>>add: (in category 'adding') -----
+ add: anObject
+ 	"Add anObject to the receiver. Store the object as well as the associated executor."
+ 	
+ 	^self add: anObject executor: anObject executor!

Item was added:
+ ----- Method: WeakRegistry>>add:executor: (in category 'adding') -----
+ add: anObject executor: anExecutor
+ 
+ 	self protected: [ | finItem |
+ 		finItem := valueDictionary at: anObject ifAbsentPut: [
+ 			WeakFinalizerItem new list: list object: anObject ].
+ 		finItem add: anExecutor ].
+ 	^ anObject
+ !

Item was added:
+ ----- Method: WeakRegistry>>do: (in category 'enumerating') -----
+ do: aBlock
+ 	^self protected: [
+ 		valueDictionary keysDo: aBlock.
+ 	].
+ !

Item was added:
+ ----- Method: WeakRegistry>>finalizeValues (in category '*System-Finalization') -----
+ finalizeValues
+ 	"Finalize any values, which happen to stocked in our list, due to some weak references become garbage"
+ 	
+ 	| finalizer |
+ 	WeakFinalizationList hasNewFinalization ifFalse: [
+ 		self protected: [
+ 			valueDictionary finalizeValues.
+ 			finalizer := executors.
+ 			executors := nil ].
+ 		finalizer ifNotNil: [
+ 			finalizer do: [ :each | each finalizeValues ] ].
+ 		^ self ].
+ 
+ 	finalizer :=  self protected: [ list swapWithNil ].
+ 
+ 	"We don't need to protect a following loop from concurrent access,
+ 	because at the moment we're finalizing values, 
+ 	only we can access this list of finalizers, because valueDictionary already see them
+ 	as an unused slots, because they're associated with key == nil"
+ 	
+ 	[ finalizer notNil ] whileTrue: [
+ 		| next |
+ 		next := finalizer next.
+ 		finalizer finalizeValues.
+ 		finalizer := next ].
+ !

Item was added:
+ ----- Method: WeakRegistry>>initialize (in category 'initialize-release') -----
+ initialize
+ 	valueDictionary := WeakIdentityKeyDictionary new.
+ 	list := WeakFinalizationList new.
+ 	sema := Semaphore forMutualExclusion.
+ 	self installFinalizer.!

Item was added:
+ ----- Method: WeakRegistry>>installFinalizer (in category 'initialize-release') -----
+ installFinalizer
+ 
+ 	valueDictionary finalizer: [ :executor |
+ 		WeakFinalizationList hasNewFinalization 
+ 			ifTrue: [ executor finalizeValues ]
+ 			ifFalse: [ 
+ 				(executors ifNil: [ executors := OrderedCollection new ]) add: executor ] ]!

Item was added:
+ ----- Method: WeakRegistry>>keys (in category 'accessing') -----
+ keys
+ 
+ 	^self protected: [ valueDictionary keys ]
+ !

Item was added:
+ ----- Method: WeakRegistry>>postCopy (in category 'copying') -----
+ postCopy
+ 	"should we prohibit any attempts to copy receiver?"
+ 	self protected: [ | oldDict |
+ 		sema := Semaphore forMutualExclusion.
+ 		oldDict := valueDictionary.
+ 		list := WeakFinalizationList new.
+ 		valueDictionary := WeakIdentityKeyDictionary new.
+ 		self installFinalizer.
+ 	
+ 		oldDict keysAndValuesDo: [:key :value |
+ 			valueDictionary at: key put: (value copyWithList: list)
+ 		].
+ 	]!

Item was added:
+ ----- Method: WeakRegistry>>printElementsOn: (in category 'printing') -----
+ printElementsOn: aStream
+ 	sema ifNil: [^super printElementsOn: aStream].
+ 	aStream nextPutAll: '(<this WeakRegistry is locked>)'!

Item was added:
+ ----- Method: WeakRegistry>>protected: (in category 'private') -----
+ protected: aBlock
+ 	"Execute aBlock protected by the accessLock"
+ 
+ 	^ sema
+ 		critical: aBlock
+ 		ifError: [ :msg :rcvr |
+ 		rcvr error: msg ] !

Item was added:
+ ----- Method: WeakRegistry>>remove:ifAbsent: (in category 'printing') -----
+ remove: oldObject ifAbsent: exceptionBlock
+ 	"Remove oldObject as one of the receiver's elements."
+ 	
+ 	oldObject ifNil: [ ^nil ].
+ 	^(self protected: [ valueDictionary removeKey: oldObject ifAbsent: nil ])
+ 		ifNil: [ exceptionBlock value ]!

Item was added:
+ ----- Method: WeakRegistry>>removeAll (in category 'printing') -----
+ removeAll
+ 	"See super"
+ 	
+ 	self protected:[
+ 		valueDictionary removeAll.
+ 	].!

Item was added:
+ ----- Method: WeakRegistry>>size (in category 'accessing') -----
+ size
+ 	^ self protected: [valueDictionary slowSize]!

Item was added:
+ ----- Method: WeakRegistry>>species (in category 'private') -----
+ species
+ 	^Set!



More information about the Squeak-dev mailing list