--- a/WeakArr.st Sat Jan 25 13:13:53 1997 +0100
+++ b/WeakArr.st Sat Jan 25 14:55:22 1997 +0100
@@ -40,7 +40,7 @@
garbage collected.
Instead, whenever an object kept in a WeakArray dies, its entry is zeroed,
and the WeakArray is informed by the storage manager. The WeakArray itself
- then informs possible dependents via te dependency mechanism.
+ 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
@@ -61,29 +61,29 @@
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.
+ 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.
[hint:]
- 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).
+ 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).
- \
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.
@@ -91,24 +91,24 @@
[instance variables:]
- dependents get informed via #change notifiction
- that the weakArray has lost pointers.
- Having the dependents here is an optimization.
+ 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 shadow tables
- and is running out of malloc-memory.
+ 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.
[author:]
- Claus Gittinger
+ Claus Gittinger
[See also:]
- Array WeakIdentitySet WeakIdentityDictionary Registry
- Model
+ Array WeakIdentitySet WeakIdentityDictionary Registry
+ Model
"
! !
@@ -129,20 +129,25 @@
new:size
"return a new weakArray with size slots"
- "This is a kludge: I would like to set WEAK-flag in the classes
+ "This is a kludge: I would like to set the WEAK-flag in the classes
initialize method, but (currently) the order in which the class-initialize
methods are called is not defined ...
... therefore it could happen, that a WeakArray is used by other
classes initialize method BEFORE this method is evaluated.
To avoid this, the WEAK bit in the class is set here, when the very first
- WeakArray is created."
+ WeakArray is created.
+ [Actually, the cleanest solution was to add another class definition
+ keyword (such as #variableWeakSubclass:) which sets the weak flag right
+ from the start.]"
AlreadyInitialized isNil ifTrue:[
- self flags:(Behavior flagWeakPointers).
- AlreadyInitialized := true
+ self flags:(Behavior flagWeakPointers).
+ AlreadyInitialized := true
].
^ (self basicNew:size) registerAsWeakArray
+
+ "Modified: 25.1.1997 / 13:17:22 / cg"
! !
!WeakArray methodsFor:'GC registration'!
@@ -158,68 +163,71 @@
ok = __addShadowObject(self, 0);
if (ok == false) {
- /*
- * this happens when too many shadow objects are
- * already there, collect garbage to get rid of
- * obsolete ones, and try again.
- * since a full collect is expensive, we try
- * a scavenge first, doing a full collect only if
- * that does not help.
- *
- * THIS MAY OR MAY NOT BE A GOOD IDEA: although it reduces
- * the number of shadow objects that have to be
- * processed at GC time, it may create a long delay here,
- * at shadow object creation time.
- * Dont know which is better ...
- */
- __nonTenuringScavenge(__context);
- ok = __addShadowObject(self, 0);
-#ifdef OLD
- if (ok == false) {
- /*
- * try more ...
- */
- __scavenge(__context);
- ok = __addShadowObject(self, 0);
-#endif
- if (ok == false) {
- /*
- * hard stuff - need full collect
- * if this is the very first GC, assume that we are in
- * the startup phase. Then do no GC.
- * Heuristics showed, that this GC does not find much ...
- */
- if ((__garbageCollectCount() != 0)
- || (__incrementalGCCount() != 0)) {
- __markAndSweepIfUseful(__context);
- ok = __addShadowObject(self, 0);
- }
- if (ok == false) {
- /*
- * mhmh - it seems that there are really many shadow
- * objects around - force creation
- */
- ok = __addShadowObject(self, 1);
- if (ok == false) {
- /* no chance - something must be wrong */
- }
- }
- }
-#ifdef OLD
- }
-#endif
+ /*
+ * the behavior of __addShadowObject() in case of overflowing
+ * VM-table space can be controlled by the second argument:
+ * if its 0, the weakObject is not registered, and false
+ * is returned.
+ * if its 1, the tables are reallocated, registration proceeds,
+ * and true is returned.
+ * This allows for the caller to have an influence on the VM's
+ * shadow table allocation.
+ *
+ * If addShadowObject() returned false, too many shadow objects are
+ * already there. Then collect garbage to get rid of
+ * obsolete ones, and try again.
+ * Since a full collect is expensive, we try
+ * a scavenge first, doing a full collect only if
+ * that does not help.
+ *
+ * THIS MAY OR MAY NOT BE A GOOD IDEA: although it reduces
+ * the number of shadow objects that have to be
+ * processed at GC time, it may create a long delay here,
+ * at shadow object creation time.
+ * Dont know which is better ...
+ */
+ __nonTenuringScavenge(__context);
+ ok = __addShadowObject(self, 0);
+
+ if (ok == false) {
+ /*
+ * hard stuff - need full collect
+ * if this is the very first GC, assume that we are in
+ * the startup phase (where all weak stuff is allocated).
+ * Then do no GC.
+ * Heuristics showed, that this GC does not find much ...
+ */
+ if ((__garbageCollectCount() != 0)
+ || (__incrementalGCCount() != 0)) {
+ __markAndSweepIfUseful(__context);
+ ok = __addShadowObject(self, 0);
+ }
+ if (ok == false) {
+ /*
+ * mhmh - it seems that there are really many shadow
+ * objects around - force creation
+ */
+ ok = __addShadowObject(self, 1);
+ if (ok == false) {
+ /*
+ * no chance - something must be wrong
+ * lets fall into the exception and see.
+ */
+ }
+ }
+ }
}
%}.
ok ifFalse:[
- "
- the VM was not able to register the new weakArray
- This can only happen, if the VM has to resize its tables,
- and a malloc request failed. Usually, this smells like big
- trouble being on the way (soon running out of memory in
- other places as well).
- Configure your OS for more swap space.
- "
- ^ RegistrationFailedSignal raiseRequestWith:self
+ "
+ the VM was not able to register the new weakArray
+ This can only happen, if the VM has to resize its tables,
+ and a malloc request failed. Usually, this smells like big
+ trouble being on the way (soon running out of memory in
+ other places as well).
+ Configure your OS for more swap space.
+ "
+ ^ RegistrationFailedSignal raiseRequestWith:self
]
! !
@@ -227,14 +235,18 @@
at:index
"return the indexed instance variable with index, anInteger.
- Reimplemented here for IGC readBarrier. You dont have to understand this."
+ Reimplemented here for IGC readBarrier.
+ (You dont have to understand this.)"
^ self basicAt:index
+
+ "Modified: 25.1.1997 / 13:41:25 / cg"
!
basicAt:index
"return the indexed instance variable with index, anInteger.
- Reimplemented here for IGC readBarrier. You dont have to understand this."
+ Reimplemented here for IGC readBarrier.
+ (You dont have to understand this.)"
%{ /* NOCONTEXT */
@@ -243,16 +255,16 @@
OBJ el;
if (__isSmallInteger(index)) {
- indx = __intVal(index) - 1;
- if (indx >= 0) {
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- indx += __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
- if (indx < nIndex) {
- el = __InstPtr(self)->i_instvars[indx];
- if (__isNonNilObject(el)) el = __WEAK_READ__(self, el);
- RETURN (el);
- }
- }
+ indx = __intVal(index) - 1;
+ if (indx >= 0) {
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ indx += __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
+ if (indx < nIndex) {
+ el = __InstPtr(self)->i_instvars[indx];
+ if (__isNonNilObject(el)) el = __WEAK_READ__(self, el);
+ RETURN (el);
+ }
+ }
}
%}.
^ super basicAt:index
@@ -403,13 +415,17 @@
forAllDeadIndicesDo:aBlock
"evaluate the argument, aBlock for all indices where elements have been
- replaced by zero (due to a collected object)."
+ replaced by zero (due to a collected object).
+ Be aware, that while indices are being enumerated, other
+ slots may change iff the garbage collector finds new garbage."
self keysAndValuesDo:[:index :element |
- element == 0 ifTrue:[
- aBlock value:index
- ]
+ element == 0 ifTrue:[
+ aBlock value:index
+ ]
]
+
+ "Modified: 25.1.1997 / 14:50:59 / cg"
!
forAllDeadIndicesDo:aBlock replacingCorpsesWith:newValue
@@ -418,14 +434,18 @@
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."
+ with future versions.
+ Be aware, that while indices are being enumerated, other
+ slots may change iff the garbage collector finds new garbage."
self keysAndValuesDo:[:index :element |
- element == 0 ifTrue:[
- self at:index put:newValue.
- aBlock value:index.
- ]
+ element == 0 ifTrue:[
+ self at:index put:newValue.
+ aBlock value:index.
+ ]
]
+
+ "Modified: 25.1.1997 / 14:51:28 / cg"
!
nilAllCorpsesAndDo:aBlock
@@ -714,6 +734,6 @@
!WeakArray class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Attic/WeakArr.st,v 1.45 1997-01-24 16:24:04 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Attic/WeakArr.st,v 1.46 1997-01-25 13:55:22 cg Exp $'
! !
WeakArray initialize!
--- a/WeakArray.st Sat Jan 25 13:13:53 1997 +0100
+++ b/WeakArray.st Sat Jan 25 14:55:22 1997 +0100
@@ -40,7 +40,7 @@
garbage collected.
Instead, whenever an object kept in a WeakArray dies, its entry is zeroed,
and the WeakArray is informed by the storage manager. The WeakArray itself
- then informs possible dependents via te dependency mechanism.
+ 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
@@ -61,29 +61,29 @@
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.
+ 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.
[hint:]
- 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).
+ 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).
- \
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.
@@ -91,24 +91,24 @@
[instance variables:]
- dependents get informed via #change notifiction
- that the weakArray has lost pointers.
- Having the dependents here is an optimization.
+ 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 shadow tables
- and is running out of malloc-memory.
+ 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.
[author:]
- Claus Gittinger
+ Claus Gittinger
[See also:]
- Array WeakIdentitySet WeakIdentityDictionary Registry
- Model
+ Array WeakIdentitySet WeakIdentityDictionary Registry
+ Model
"
! !
@@ -129,20 +129,25 @@
new:size
"return a new weakArray with size slots"
- "This is a kludge: I would like to set WEAK-flag in the classes
+ "This is a kludge: I would like to set the WEAK-flag in the classes
initialize method, but (currently) the order in which the class-initialize
methods are called is not defined ...
... therefore it could happen, that a WeakArray is used by other
classes initialize method BEFORE this method is evaluated.
To avoid this, the WEAK bit in the class is set here, when the very first
- WeakArray is created."
+ WeakArray is created.
+ [Actually, the cleanest solution was to add another class definition
+ keyword (such as #variableWeakSubclass:) which sets the weak flag right
+ from the start.]"
AlreadyInitialized isNil ifTrue:[
- self flags:(Behavior flagWeakPointers).
- AlreadyInitialized := true
+ self flags:(Behavior flagWeakPointers).
+ AlreadyInitialized := true
].
^ (self basicNew:size) registerAsWeakArray
+
+ "Modified: 25.1.1997 / 13:17:22 / cg"
! !
!WeakArray methodsFor:'GC registration'!
@@ -158,68 +163,71 @@
ok = __addShadowObject(self, 0);
if (ok == false) {
- /*
- * this happens when too many shadow objects are
- * already there, collect garbage to get rid of
- * obsolete ones, and try again.
- * since a full collect is expensive, we try
- * a scavenge first, doing a full collect only if
- * that does not help.
- *
- * THIS MAY OR MAY NOT BE A GOOD IDEA: although it reduces
- * the number of shadow objects that have to be
- * processed at GC time, it may create a long delay here,
- * at shadow object creation time.
- * Dont know which is better ...
- */
- __nonTenuringScavenge(__context);
- ok = __addShadowObject(self, 0);
-#ifdef OLD
- if (ok == false) {
- /*
- * try more ...
- */
- __scavenge(__context);
- ok = __addShadowObject(self, 0);
-#endif
- if (ok == false) {
- /*
- * hard stuff - need full collect
- * if this is the very first GC, assume that we are in
- * the startup phase. Then do no GC.
- * Heuristics showed, that this GC does not find much ...
- */
- if ((__garbageCollectCount() != 0)
- || (__incrementalGCCount() != 0)) {
- __markAndSweepIfUseful(__context);
- ok = __addShadowObject(self, 0);
- }
- if (ok == false) {
- /*
- * mhmh - it seems that there are really many shadow
- * objects around - force creation
- */
- ok = __addShadowObject(self, 1);
- if (ok == false) {
- /* no chance - something must be wrong */
- }
- }
- }
-#ifdef OLD
- }
-#endif
+ /*
+ * the behavior of __addShadowObject() in case of overflowing
+ * VM-table space can be controlled by the second argument:
+ * if its 0, the weakObject is not registered, and false
+ * is returned.
+ * if its 1, the tables are reallocated, registration proceeds,
+ * and true is returned.
+ * This allows for the caller to have an influence on the VM's
+ * shadow table allocation.
+ *
+ * If addShadowObject() returned false, too many shadow objects are
+ * already there. Then collect garbage to get rid of
+ * obsolete ones, and try again.
+ * Since a full collect is expensive, we try
+ * a scavenge first, doing a full collect only if
+ * that does not help.
+ *
+ * THIS MAY OR MAY NOT BE A GOOD IDEA: although it reduces
+ * the number of shadow objects that have to be
+ * processed at GC time, it may create a long delay here,
+ * at shadow object creation time.
+ * Dont know which is better ...
+ */
+ __nonTenuringScavenge(__context);
+ ok = __addShadowObject(self, 0);
+
+ if (ok == false) {
+ /*
+ * hard stuff - need full collect
+ * if this is the very first GC, assume that we are in
+ * the startup phase (where all weak stuff is allocated).
+ * Then do no GC.
+ * Heuristics showed, that this GC does not find much ...
+ */
+ if ((__garbageCollectCount() != 0)
+ || (__incrementalGCCount() != 0)) {
+ __markAndSweepIfUseful(__context);
+ ok = __addShadowObject(self, 0);
+ }
+ if (ok == false) {
+ /*
+ * mhmh - it seems that there are really many shadow
+ * objects around - force creation
+ */
+ ok = __addShadowObject(self, 1);
+ if (ok == false) {
+ /*
+ * no chance - something must be wrong
+ * lets fall into the exception and see.
+ */
+ }
+ }
+ }
}
%}.
ok ifFalse:[
- "
- the VM was not able to register the new weakArray
- This can only happen, if the VM has to resize its tables,
- and a malloc request failed. Usually, this smells like big
- trouble being on the way (soon running out of memory in
- other places as well).
- Configure your OS for more swap space.
- "
- ^ RegistrationFailedSignal raiseRequestWith:self
+ "
+ the VM was not able to register the new weakArray
+ This can only happen, if the VM has to resize its tables,
+ and a malloc request failed. Usually, this smells like big
+ trouble being on the way (soon running out of memory in
+ other places as well).
+ Configure your OS for more swap space.
+ "
+ ^ RegistrationFailedSignal raiseRequestWith:self
]
! !
@@ -227,14 +235,18 @@
at:index
"return the indexed instance variable with index, anInteger.
- Reimplemented here for IGC readBarrier. You dont have to understand this."
+ Reimplemented here for IGC readBarrier.
+ (You dont have to understand this.)"
^ self basicAt:index
+
+ "Modified: 25.1.1997 / 13:41:25 / cg"
!
basicAt:index
"return the indexed instance variable with index, anInteger.
- Reimplemented here for IGC readBarrier. You dont have to understand this."
+ Reimplemented here for IGC readBarrier.
+ (You dont have to understand this.)"
%{ /* NOCONTEXT */
@@ -243,16 +255,16 @@
OBJ el;
if (__isSmallInteger(index)) {
- indx = __intVal(index) - 1;
- if (indx >= 0) {
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- indx += __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
- if (indx < nIndex) {
- el = __InstPtr(self)->i_instvars[indx];
- if (__isNonNilObject(el)) el = __WEAK_READ__(self, el);
- RETURN (el);
- }
- }
+ indx = __intVal(index) - 1;
+ if (indx >= 0) {
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ indx += __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
+ if (indx < nIndex) {
+ el = __InstPtr(self)->i_instvars[indx];
+ if (__isNonNilObject(el)) el = __WEAK_READ__(self, el);
+ RETURN (el);
+ }
+ }
}
%}.
^ super basicAt:index
@@ -403,13 +415,17 @@
forAllDeadIndicesDo:aBlock
"evaluate the argument, aBlock for all indices where elements have been
- replaced by zero (due to a collected object)."
+ replaced by zero (due to a collected object).
+ Be aware, that while indices are being enumerated, other
+ slots may change iff the garbage collector finds new garbage."
self keysAndValuesDo:[:index :element |
- element == 0 ifTrue:[
- aBlock value:index
- ]
+ element == 0 ifTrue:[
+ aBlock value:index
+ ]
]
+
+ "Modified: 25.1.1997 / 14:50:59 / cg"
!
forAllDeadIndicesDo:aBlock replacingCorpsesWith:newValue
@@ -418,14 +434,18 @@
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."
+ with future versions.
+ Be aware, that while indices are being enumerated, other
+ slots may change iff the garbage collector finds new garbage."
self keysAndValuesDo:[:index :element |
- element == 0 ifTrue:[
- self at:index put:newValue.
- aBlock value:index.
- ]
+ element == 0 ifTrue:[
+ self at:index put:newValue.
+ aBlock value:index.
+ ]
]
+
+ "Modified: 25.1.1997 / 14:51:28 / cg"
!
nilAllCorpsesAndDo:aBlock
@@ -714,6 +734,6 @@
!WeakArray class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/WeakArray.st,v 1.45 1997-01-24 16:24:04 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/WeakArray.st,v 1.46 1997-01-25 13:55:22 cg Exp $'
! !
WeakArray initialize!