Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r1279:3751a1489e7b
Date: 2013-07-18 18:12 +0200
http://bitbucket.org/cffi/cffi/changeset/3751a1489e7b/

Log:    I think that this should clean up the (relative) mess of the GC on
        some-but-not-all cdata objects. The test still doesn't pass though.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -144,11 +144,14 @@
 static PyTypeObject CField_Type;
 static PyTypeObject CData_Type;
 static PyTypeObject CDataOwning_Type;
+static PyTypeObject CDataOwningGC_Type;
 
 #define CTypeDescr_Check(ob)  (Py_TYPE(ob) == &CTypeDescr_Type)
 #define CData_Check(ob)       (Py_TYPE(ob) == &CData_Type ||            \
-                               Py_TYPE(ob) == &CDataOwning_Type)
-#define CDataOwn_Check(ob)    (Py_TYPE(ob) == &CDataOwning_Type)
+                               Py_TYPE(ob) == &CDataOwning_Type ||      \
+                               Py_TYPE(ob) == &CDataOwningGC_Type)
+#define CDataOwn_Check(ob)    (Py_TYPE(ob) == &CDataOwning_Type ||      \
+                               Py_TYPE(ob) == &CDataOwningGC_Type)
 
 typedef union {
     unsigned char m_char;
@@ -561,13 +564,6 @@
     PyObject_Del(cf);
 }
 
-static int
-cfield_traverse(CFieldObject *cf, visitproc visit, void *arg)
-{
-    Py_VISIT(cf->cf_type);
-    return 0;
-}
-
 #undef OFF
 #define OFF(x) offsetof(CFieldObject, x)
 
@@ -602,7 +598,7 @@
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
     0,                                          /* tp_doc */
-    (traverseproc)cfield_traverse,              /* tp_traverse */
+    0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
     0,                                          /* tp_richcompare */
     0,                                          /* tp_weaklistoffset */
@@ -1384,26 +1380,17 @@
 
     Py_DECREF(cd->c_type);
 #ifndef CFFI_MEM_LEAK     /* never release anything, tests only */
-    PyObject_Del(cd);
+    Py_TYPE(cd)->tp_free((PyObject *)cd);
 #endif
 }
 
 static void cdataowning_dealloc(CDataObject *cd)
 {
+    assert(!(cd->c_type->ct_flags & (CT_IS_VOID_PTR | CT_FUNCTIONPTR)));
+
     if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
         Py_DECREF(((CDataObject_own_structptr *)cd)->structobj);
     }
-    else if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {
-        PyObject *x = (PyObject *)(cd->c_data + 42);
-        Py_DECREF(x);
-    }
-    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {
-        /* a callback */
-        ffi_closure *closure = (ffi_closure *)cd->c_data;
-        PyObject *args = (PyObject *)(closure->user_data);
-        Py_XDECREF(args);
-        cffi_closure_free(closure);
-    }
 #if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK)
     if (cd->c_type->ct_flags & (CT_PRIMITIVE_ANY | CT_STRUCT | CT_UNION)) {
         assert(cd->c_type->ct_size >= 0);
@@ -1420,28 +1407,55 @@
     cdata_dealloc(cd);
 }
 
-static int cdata_traverse(CDataObject *cd, visitproc visit, void *arg)
+static void cdataowninggc_dealloc(CDataObject *cd)
 {
-    /* XXX needs Py_TPFLAGS_HAVE_GC */
-    Py_VISIT(cd->c_type);
-    return 0;
+    assert(!(cd->c_type->ct_flags & (CT_IS_PTR_TO_OWNED |
+                                     CT_PRIMITIVE_ANY |
+                                     CT_STRUCT | CT_UNION)));
+    PyObject_GC_UnTrack(cd);
+
+    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
+        PyObject *x = (PyObject *)(cd->c_data + 42);
+        Py_DECREF(x);
+    }
+    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
+        ffi_closure *closure = (ffi_closure *)cd->c_data;
+        PyObject *args = (PyObject *)(closure->user_data);
+        Py_XDECREF(args);
+        cffi_closure_free(closure);
+    }
+    cdata_dealloc(cd);
 }
 
-static int cdataowning_traverse(CDataObject *cd, visitproc visit, void *arg)
+static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg)
 {
-    if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
-        Py_VISIT(((CDataObject_own_structptr *)cd)->structobj);
-    }
-    else if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {
+    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
         PyObject *x = (PyObject *)(cd->c_data + 42);
         Py_VISIT(x);
     }
-    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {
+    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
         ffi_closure *closure = (ffi_closure *)cd->c_data;
         PyObject *args = (PyObject *)(closure->user_data);
         Py_VISIT(args);
     }
-    return cdata_traverse(cd, visit, arg);
+    return 0;
+}
+
+static int cdataowninggc_clear(CDataObject *cd)
+{
+    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
+        PyObject *x = (PyObject *)(cd->c_data + 42);
+        Py_INCREF(Py_None);
+        cd->c_data = ((char *)Py_None) - 42;
+        Py_DECREF(x);
+    }
+    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
+        ffi_closure *closure = (ffi_closure *)cd->c_data;
+        PyObject *args = (PyObject *)(closure->user_data);
+        closure->user_data = NULL;
+        Py_XDECREF(args);
+    }
+    return 0;
 }
 
 static PyObject *cdata_float(CDataObject *cd);  /*forward*/
@@ -2415,7 +2429,7 @@
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
     0,                                          /* tp_doc */
-    (traverseproc)cdata_traverse,               /* tp_traverse */
+    0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
     cdata_richcompare,                          /* tp_richcompare */
     offsetof(CDataObject, c_weakreflist),       /* tp_weaklistoffset */
@@ -2445,7 +2459,7 @@
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
     0,                                          /* tp_doc */
-    (traverseproc)cdataowning_traverse,         /* tp_traverse */
+    0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
     0,                                          /* tp_richcompare */
     0,                                          /* tp_weaklistoffset */
@@ -2457,6 +2471,41 @@
     &CData_Type,                                /* tp_base */
 };
 
+static PyTypeObject CDataOwningGC_Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_cffi_backend.CDataOwnGC",
+    sizeof(CDataObject),
+    0,
+    (destructor)cdataowninggc_dealloc,          /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES  /* tp_flags */
+                       | Py_TPFLAGS_HAVE_GC,
+    0,                                          /* tp_doc */
+    (traverseproc)cdataowninggc_traverse,       /* tp_traverse */
+    (inquiry)cdataowninggc_clear,               /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    0,                                          /* tp_methods */
+    0,                                          /* tp_members */
+    0,                                          /* tp_getset */
+    &CDataOwning_Type,                          /* tp_base */
+};
+
 /************************************************************/
 
 typedef struct {
@@ -4364,7 +4413,7 @@
 
     closure = cffi_closure_alloc();
 
-    cd = PyObject_New(CDataObject, &CDataOwning_Type);
+    cd = PyObject_GC_New(CDataObject, &CDataOwningGC_Type);
     if (cd == NULL)
         goto error;
     Py_INCREF(ct);
@@ -4799,12 +4848,14 @@
         return NULL;
     }
 
-    cd = allocate_owning_object(sizeof(CDataObject), ct);
+    cd = (CDataObject *)PyObject_GC_New(CDataObject, &CDataOwningGC_Type);
     if (cd == NULL)
         return NULL;
-
+    Py_INCREF(ct);
+    cd->c_type = ct;
     Py_INCREF(x);
     cd->c_data = ((char *)x) - 42;
+    cd->c_weakreflist = NULL;
     return (PyObject *)cd;
 }
 
@@ -5278,6 +5329,8 @@
         INITERROR;
     if (PyType_Ready(&CDataOwning_Type) < 0)
         INITERROR;
+    if (PyType_Ready(&CDataOwningGC_Type) < 0)
+        INITERROR;
     if (PyType_Ready(&CDataIter_Type) < 0)
         INITERROR;
     if (PyType_Ready(&MiniBuffer_Type) < 0)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to