commentary
authorClaus Gittinger <cg@exept.de>
Sat, 25 Jan 1997 14:55:22 +0100
changeset 2271 65fe1df5b0b3
parent 2270 76c239686353
child 2272 9942d9c853c3
commentary
WeakArr.st
WeakArray.st
--- 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!