[Python-checkins] python/dist/src/Modules gcmodule.c,2.58,2.59

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
Fri, 04 Apr 2003 11:59:10 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv829

Modified Files:
	gcmodule.c 
Log Message:
Fix Tim's boom example.

move_finalizers() moves every object from unreachable to collectable
or finalizers, unless the object is deallocated first.


Index: gcmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/gcmodule.c,v
retrieving revision 2.58
retrieving revision 2.59
diff -C2 -d -r2.58 -r2.59
*** gcmodule.c	3 Apr 2003 16:29:13 -0000	2.58
--- gcmodule.c	4 Apr 2003 19:59:06 -0000	2.59
***************
*** 60,63 ****
--- 60,66 ----
  static PyObject *gc_str;
  
+ /* Python string used to looked for __del__ attribute. */
+ static PyObject *delstr;
+ 
  /* set for debugging information */
  #define DEBUG_STATS		(1<<0) /* print collection statistics */
***************
*** 341,350 ****
  has_finalizer(PyObject *op)
  {
- 	static PyObject *delstr = NULL;
- 	if (delstr == NULL) {
- 		delstr = PyString_InternFromString("__del__");
- 		if (delstr == NULL)
- 			Py_FatalError("PyGC: can't initialize __del__ string");
- 	}
  	return PyInstance_Check(op) ? PyObject_HasAttr(op, delstr) :
  	        PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE) ?
--- 344,347 ----
***************
*** 352,369 ****
  }
  
! /* Move all objects with finalizers (instances with __del__) */
  static void
! move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
  {
! 	PyGC_Head *next;
! 	PyGC_Head *gc = unreachable->gc.gc_next;
! 	for (; gc != unreachable; gc=next) {
  		PyObject *op = FROM_GC(gc);
! 		next = gc->gc.gc_next;
! 		if (has_finalizer(op)) {
  			gc_list_remove(gc);
  			gc_list_append(gc, finalizers);
  			gc->gc.gc_refs = GC_REACHABLE;
  		}
  	}
  }
--- 349,393 ----
  }
  
! /* Move all objects out of unreachable and into collectable or finalizers.
!  */
  static void
! move_finalizers(PyGC_Head *unreachable, PyGC_Head *collectable,
! 		PyGC_Head *finalizers)
  {
! 	while (!gc_list_is_empty(unreachable)) {
! 		PyGC_Head *gc = unreachable->gc.gc_next;
  		PyObject *op = FROM_GC(gc);
! 		int finalizer;
! 
! 		if (PyInstance_Check(op)) {
! 			/* The HasAttr() check may run enough Python
! 			   code to deallocate the object or make it
! 			   reachable again.  INCREF the object before
! 			   calling HasAttr() to guard against the client
! 			   code deallocating the object.
! 			*/
! 			Py_INCREF(op);
! 			finalizer = PyObject_HasAttr(op, delstr);
! 			if (op->ob_refcnt == 1) {
! 				/* The object will be deallocated. 
! 				   Nothing left to do.
! 				 */
! 				Py_DECREF(op);
! 				continue;
! 			}
! 			Py_DECREF(op);
! 		}
! 		else
! 			finalizer = has_finalizer(op);
! 		if (finalizer) {
  			gc_list_remove(gc);
  			gc_list_append(gc, finalizers);
  			gc->gc.gc_refs = GC_REACHABLE;
  		}
+ 		else {
+ 			gc_list_remove(gc);
+ 			gc_list_append(gc, collectable);
+ 			/* XXX change gc_refs? */
+ 		}
  	}
  }
***************
*** 438,441 ****
--- 462,466 ----
  			gc = finalizers->gc.gc_next) {
  		PyObject *op = FROM_GC(gc);
+ 		/* XXX has_finalizer() is not safe here. */
  		if ((debug & DEBUG_SAVEALL) || has_finalizer(op)) {
  			/* If SAVEALL is not set then just append objects with
***************
*** 458,467 ****
   */
  static void
! delete_garbage(PyGC_Head *unreachable, PyGC_Head *old)
  {
  	inquiry clear;
  
! 	while (!gc_list_is_empty(unreachable)) {
! 		PyGC_Head *gc = unreachable->gc.gc_next;
  		PyObject *op = FROM_GC(gc);
  
--- 483,492 ----
   */
  static void
! delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
  {
  	inquiry clear;
  
! 	while (!gc_list_is_empty(collectable)) {
! 		PyGC_Head *gc = collectable->gc.gc_next;
  		PyObject *op = FROM_GC(gc);
  
***************
*** 477,481 ****
  			}
  		}
! 		if (unreachable->gc.gc_next == gc) {
  			/* object is still alive, move it, it may die later */
  			gc_list_remove(gc);
--- 502,506 ----
  			}
  		}
! 		if (collectable->gc.gc_next == gc) {
  			/* object is still alive, move it, it may die later */
  			gc_list_remove(gc);
***************
*** 497,500 ****
--- 522,526 ----
  	PyGC_Head *old; /* next older generation */
  	PyGC_Head unreachable;
+ 	PyGC_Head collectable;
  	PyGC_Head finalizers;
  	PyGC_Head *gc;
***************
*** 553,564 ****
  	 * care not to create such things.  For Python, finalizers means
  	 * instance objects with __del__ methods.
  	 */
  	gc_list_init(&finalizers);
! 	move_finalizers(&unreachable, &finalizers);
  	move_finalizer_reachable(&finalizers);
  
  	/* Collect statistics on collectable objects found and print
  	 * debugging information. */
! 	for (gc = unreachable.gc.gc_next; gc != &unreachable;
  			gc = gc->gc.gc_next) {
  		m++;
--- 579,595 ----
  	 * care not to create such things.  For Python, finalizers means
  	 * instance objects with __del__ methods.
+ 	 * 
+ 	 * Move each object into the collectable set or the finalizers set.
+ 	 * It's possible that a classic class with a getattr() hook will
+ 	 * be revived or deallocated in this step.
  	 */
+ 	gc_list_init(&collectable);
  	gc_list_init(&finalizers);
! 	move_finalizers(&unreachable, &collectable, &finalizers);
  	move_finalizer_reachable(&finalizers);
  
  	/* Collect statistics on collectable objects found and print
  	 * debugging information. */
! 	for (gc = collectable.gc.gc_next; gc != &collectable;
  			gc = gc->gc.gc_next) {
  		m++;
***************
*** 570,574 ****
  	 * the reference cycles to be broken. It may also cause some objects in
  	 * finalizers to be freed */
! 	delete_garbage(&unreachable, old);
  
  	/* Collect statistics on uncollectable objects found and print
--- 601,605 ----
  	 * the reference cycles to be broken. It may also cause some objects in
  	 * finalizers to be freed */
! 	delete_garbage(&collectable, old);
  
  	/* Collect statistics on uncollectable objects found and print
***************
*** 939,942 ****
--- 970,976 ----
  	PyObject *d;
  
+ 	delstr = PyString_InternFromString("__del__");
+ 	if (!delstr)
+ 		return;
  	m = Py_InitModule4("gc",
  			      GcMethods,