From 13423bbbafc823740126e90ef0d7ca6e76fc7341 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 21 Jun 2009 19:47:31 +0200 Subject: python: Make all CppOwnedPyObjects and similar support garbage collection. If you want to subclass apt_pkg.Cache() and create an apt_pkg.DepCache() object in it (e.g. as self.depcache) this is needed because otherwise, Python would not know about the cyclic dependency and refuse to free any of them. This also changes apt_pkg.Cache to the standard deallocation schema, because the underlying CacheFile deletes its pointers automatically on deletion. Thus a second call is not needed. --- python/generic.h | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'python/generic.h') diff --git a/python/generic.h b/python/generic.h index b7b958f5..a9e6b8bf 100644 --- a/python/generic.h +++ b/python/generic.h @@ -29,6 +29,7 @@ #include #include +#include #include #if PYTHON_API_VERSION < 1013 @@ -99,6 +100,9 @@ inline PyObject *GetOwner(PyObject *Obj) template inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << " ===\n"; + #endif CppPyObject *New = (CppPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; return New; @@ -107,6 +111,9 @@ inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type) template inline CppPyObject *CppPyObject_NEW(PyTypeObject *Type,A const &Arg) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << " ===\n"; + #endif CppPyObject *New = (CppPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); return New; @@ -116,6 +123,9 @@ template inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n"; + #endif CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T; New->Owner = Owner; @@ -127,6 +137,9 @@ template inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type,A const &Arg) { + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n"; + #endif CppOwnedPyObject *New = (CppOwnedPyObject*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); New->Owner = Owner; @@ -135,10 +148,26 @@ inline CppOwnedPyObject *CppOwnedPyObject_NEW(PyObject *Owner, return New; } +// Traversal and Clean for owned objects +template +int CppOwnedTraverse(PyObject *self, visitproc visit, void* arg) { + Py_VISIT(((CppOwnedPyObject *)self)->Owner); + return 0; +} + +template +int CppOwnedClear(PyObject *self) { + Py_CLEAR(((CppOwnedPyObject *)self)->Owner); + return 0; +} + // Generic Dealloc type functions template void CppDealloc(PyObject *Obj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << " ===\n"; + #endif GetCpp(Obj).~T(); Obj->ob_type->tp_free(Obj); } @@ -146,10 +175,12 @@ void CppDealloc(PyObject *Obj) template void CppOwnedDealloc(PyObject *iObj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "+ ===\n"; + #endif CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; Obj->Object.~T(); - if (Obj->Owner != 0) - Py_DECREF(Obj->Owner); + CppOwnedClear(iObj); iObj->ob_type->tp_free(iObj); } @@ -158,6 +189,9 @@ void CppOwnedDealloc(PyObject *iObj) template void CppDeallocPtr(PyObject *Obj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "* ===\n"; + #endif delete GetCpp(Obj); Obj->ob_type->tp_free(Obj); } @@ -165,10 +199,12 @@ void CppDeallocPtr(PyObject *Obj) template void CppOwnedDeallocPtr(PyObject *iObj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "*+ ===\n"; + #endif CppOwnedPyObject *Obj = (CppOwnedPyObject *)iObj; delete Obj->Object; - if (Obj->Owner != 0) - Py_DECREF(Obj->Owner); + CppOwnedClear(iObj); iObj->ob_type->tp_free(iObj); } -- cgit v1.2.3