[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.115,2.116
Guido van Rossum
gvanrossum@users.sourceforge.net
Mon, 29 Oct 2001 14:09:39 -0800
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv22912
Modified Files:
typeobject.c
Log Message:
Add __del__ callbacks. They are too useful to leave out.
XXX Remaining problems:
- The GC module doesn't know about these; I think it has its reasons
to disallow calling __del__, but for now, __del__ on new-style
objects is called when the GC module discards an object, for better
or for worse.
- The code to call a __del__ handler is really ridiculously
complicated, due to all the different debug #ifdefs. I've copied
this from the similar code in classobject.c, so I'm pretty sure I
did it right, but it's not pretty. :-(
- No tests yet.
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.115
retrieving revision 2.116
diff -C2 -d -r2.115 -r2.116
*** typeobject.c 2001/10/29 14:33:44 2.115
--- typeobject.c 2001/10/29 22:09:37 2.116
***************
*** 231,234 ****
--- 231,305 ----
}
+ staticforward PyObject *lookup_maybe(PyObject *, char *, PyObject **);
+
+ static int
+ call_finalizer(PyObject *self)
+ {
+ static PyObject *del_str = NULL;
+ PyObject *del, *res;
+ PyObject *error_type, *error_value, *error_traceback;
+
+ /* Temporarily resurrect the object. */
+ #ifdef Py_TRACE_REFS
+ #ifndef Py_REF_DEBUG
+ # error "Py_TRACE_REFS defined but Py_REF_DEBUG not."
+ #endif
+ /* much too complicated if Py_TRACE_REFS defined */
+ _Py_NewReference((PyObject *)self);
+ #ifdef COUNT_ALLOCS
+ /* compensate for boost in _Py_NewReference; note that
+ * _Py_RefTotal was also boosted; we'll knock that down later.
+ */
+ self->ob_type->tp_allocs--;
+ #endif
+ #else /* !Py_TRACE_REFS */
+ /* Py_INCREF boosts _Py_RefTotal if Py_REF_DEBUG is defined */
+ Py_INCREF(self);
+ #endif /* !Py_TRACE_REFS */
+
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ /* Execute __del__ method, if any. */
+ del = lookup_maybe(self, "__del__", &del_str);
+ if (del != NULL) {
+ res = PyEval_CallObject(del, NULL);
+ if (res == NULL)
+ PyErr_WriteUnraisable(del);
+ else
+ Py_DECREF(res);
+ Py_DECREF(del);
+ }
+
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+
+ /* Undo the temporary resurrection; can't use DECREF here, it would
+ * cause a recursive call.
+ */
+ #ifdef Py_REF_DEBUG
+ /* _Py_RefTotal was boosted either by _Py_NewReference or
+ * Py_INCREF above.
+ */
+ _Py_RefTotal--;
+ #endif
+ if (--self->ob_refcnt > 0) {
+ #ifdef COUNT_ALLOCS
+ self->ob_type->tp_frees--;
+ #endif
+ _PyObject_GC_TRACK(self);
+ return -1; /* __del__ added a reference; don't delete now */
+ }
+ #ifdef Py_TRACE_REFS
+ _Py_ForgetReference((PyObject *)self);
+ #ifdef COUNT_ALLOCS
+ /* compensate for increment in _Py_ForgetReference */
+ self->ob_type->tp_frees--;
+ #endif
+ #endif
+
+ return 0;
+ }
+
static void
subtype_dealloc(PyObject *self)
***************
*** 238,241 ****
--- 309,315 ----
/* This exists so we can DECREF self->ob_type */
+
+ if (call_finalizer(self) < 0)
+ return;
/* Find the nearest base with a different tp_dealloc */