[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,