[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.115,2.116

Guido van Rossum gvanrossum@users.sourceforge.net
2001年10月29日 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 */

AltStyle によって変換されたページ (->オリジナル) /