Author: Armin Rigo <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit