[pypy-commit] cffi default: Support for weakrefs.
arigo
noreply at buildbot.pypy.org
Sat Jun 23 09:59:39 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r490:108f2d1c26e5
Date: 2012-06-23 09:59 +0200
http://bitbucket.org/cffi/cffi/changeset/108f2d1c26e5/
Log: Support for weakrefs.
diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -58,6 +58,8 @@
function types: cif_description
primitives: prebuilt "cif" object */
+ PyObject *ct_weakreflist; /* weakref support */
+
Py_ssize_t ct_size; /* size of instances, or -1 if unknown */
Py_ssize_t ct_length; /* length of arrays, or -1 if unknown;
or alignment of primitive and struct types */
@@ -104,13 +106,23 @@
typedef struct {
CDataObject head;
union_alignment alignment;
-} CDataObject_with_alignment;
+} CDataObject_casted_primitive;
typedef struct {
CDataObject head;
+ PyObject *weakreflist;
+} CDataObject_own_base;
+
+typedef struct {
+ CDataObject_own_base head;
+ union_alignment alignment;
+} CDataObject_own_nolength;
+
+typedef struct {
+ CDataObject_own_base head;
Py_ssize_t length;
union_alignment alignment;
-} CDataObject_with_length;
+} CDataObject_own_length;
typedef struct {
ffi_cif cif;
@@ -151,6 +163,7 @@
ct->ct_itemdescr = NULL;
ct->ct_stuff = NULL;
+ ct->ct_weakreflist = NULL;
PyObject_GC_Track(ct);
return ct;
}
@@ -191,6 +204,8 @@
ctypedescr_dealloc(CTypeDescrObject *ct)
{
PyObject_GC_UnTrack(ct);
+ if (ct->ct_weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *) ct);
Py_XDECREF(ct->ct_itemdescr);
Py_XDECREF(ct->ct_stuff);
if (ct->ct_flags & CT_FUNCTIONPTR)
@@ -238,6 +253,8 @@
0, /* tp_doc */
(traverseproc)ctypedescr_traverse, /* tp_traverse */
(inquiry)ctypedescr_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(CTypeDescrObject, ct_weakreflist), /* tp_weaklistoffset */
};
/************************************************************/
@@ -935,7 +952,7 @@
get_array_length(CDataObject *cd)
{
if (cd->c_type->ct_length < 0)
- return ((CDataObject_with_length *)cd)->length;
+ return ((CDataObject_own_length *)cd)->length;
else
return cd->c_type->ct_length;
}
@@ -977,16 +994,19 @@
PyObject_Del(cd);
}
-static void cdataowning_dealloc(CDataObject *cd)
+static void cdataowning_dealloc(CDataObject_own_base *cdb)
{
- if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {
+ if (cdb->weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *) cdb);
+
+ if (cdb->head.c_type->ct_flags & CT_FUNCTIONPTR) {
/* a callback */
- ffi_closure *closure = (ffi_closure *)cd->c_data;
+ ffi_closure *closure = (ffi_closure *)cdb->head.c_data;
PyObject *args = (PyObject *)(closure->user_data);
Py_XDECREF(args);
cffi_closure_free(closure);
}
- cdata_dealloc(cd);
+ cdata_dealloc(&cdb->head);
}
static int cdata_traverse(CDataObject *cd, visitproc visit, void *arg)
@@ -1590,7 +1610,7 @@
static PyTypeObject CDataOwning_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_ffi_backend.CDataOwn",
- sizeof(CDataObject),
+ sizeof(CDataObject_own_base),
0,
(destructor)cdataowning_dealloc, /* tp_dealloc */
0, /* tp_print */
@@ -1612,7 +1632,7 @@
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
+ offsetof(CDataObject_own_base, weakreflist),/* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
@@ -1707,7 +1727,7 @@
static PyObject *b_newp(PyObject *self, PyObject *args)
{
CTypeDescrObject *ct, *ctitem;
- CDataObject *cd;
+ CDataObject_own_base *cdb;
PyObject *init;
Py_ssize_t dataoffset, datasize, explicitlength;
if (!PyArg_ParseTuple(args, "O!O:newp", &CTypeDescr_Type, &ct, &init))
@@ -1715,7 +1735,7 @@
explicitlength = -1;
if (ct->ct_flags & CT_POINTER) {
- dataoffset = offsetof(CDataObject_with_alignment, alignment);
+ dataoffset = offsetof(CDataObject_own_nolength, alignment);
ctitem = ct->ct_itemdescr;
datasize = ctitem->ct_size;
if (datasize < 0) {
@@ -1728,7 +1748,7 @@
datasize += sizeof(char); /* forcefully add a null character */
}
else if (ct->ct_flags & CT_ARRAY) {
- dataoffset = offsetof(CDataObject_with_alignment, alignment);
+ dataoffset = offsetof(CDataObject_own_nolength, alignment);
datasize = ct->ct_size;
if (datasize < 0) {
if (PyList_Check(init) || PyTuple_Check(init)) {
@@ -1749,7 +1769,7 @@
init = Py_None;
}
ctitem = ct->ct_itemdescr;
- dataoffset = offsetof(CDataObject_with_length, alignment);
+ dataoffset = offsetof(CDataObject_own_length, alignment);
datasize = explicitlength * ctitem->ct_size;
if (explicitlength > 0 &&
(datasize / explicitlength) != ctitem->ct_size) {
@@ -1764,30 +1784,31 @@
return NULL;
}
- cd = (CDataObject *)PyObject_Malloc(dataoffset + datasize);
- if (PyObject_Init((PyObject *)cd, &CDataOwning_Type) == NULL)
+ cdb = (CDataObject_own_base *)PyObject_Malloc(dataoffset + datasize);
+ if (PyObject_Init((PyObject *)cdb, &CDataOwning_Type) == NULL)
return NULL;
Py_INCREF(ct);
- cd->c_type = ct;
- cd->c_data = ((char *)cd) + dataoffset;
+ cdb->head.c_type = ct;
+ cdb->head.c_data = ((char *)cdb) + dataoffset;
+ cdb->weakreflist = NULL;
if (explicitlength >= 0)
- ((CDataObject_with_length*)cd)->length = explicitlength;
-
- memset(cd->c_data, 0, datasize);
+ ((CDataObject_own_length*)cdb)->length = explicitlength;
+
+ memset(cdb->head.c_data, 0, datasize);
if (init != Py_None) {
- if (convert_from_object(cd->c_data,
+ if (convert_from_object(cdb->head.c_data,
(ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct, init) < 0) {
- Py_DECREF(cd);
+ Py_DECREF(cdb);
return NULL;
}
}
- return (PyObject *)cd;
+ return (PyObject *)cdb;
}
static CDataObject *_new_casted_primitive(CTypeDescrObject *ct)
{
- int dataoffset = offsetof(CDataObject_with_alignment, alignment);
+ int dataoffset = offsetof(CDataObject_casted_primitive, alignment);
CDataObject *cd = (CDataObject *)PyObject_Malloc(dataoffset + ct->ct_size);
if (PyObject_Init((PyObject *)cd, &CData_Type) == NULL)
return NULL;
@@ -2986,7 +3007,7 @@
static PyObject *b_callback(PyObject *self, PyObject *args)
{
CTypeDescrObject *ct;
- CDataObject *cd;
+ CDataObject_own_base *cdb;
PyObject *ob;
cif_description_t *cif_descr;
ffi_closure *closure;
@@ -3008,12 +3029,13 @@
closure = cffi_closure_alloc();
- cd = PyObject_New(CDataObject, &CDataOwning_Type);
- if (cd == NULL)
+ cdb = PyObject_New(CDataObject_own_base, &CDataOwning_Type);
+ if (cdb == NULL)
goto error;
Py_INCREF(ct);
- cd->c_type = ct;
- cd->c_data = (char *)closure;
+ cdb->head.c_type = ct;
+ cdb->head.c_data = (char *)closure;
+ cdb->weakreflist = NULL;
cif_descr = (cif_description_t *)ct->ct_extra;
if (cif_descr == NULL) {
@@ -3029,14 +3051,14 @@
}
assert(closure->user_data == args);
Py_INCREF(args); /* capture the tuple (CTypeDescr, Python callable) */
- return (PyObject *)cd;
+ return (PyObject *)cdb;
error:
closure->user_data = NULL;
- if (cd == NULL)
+ if (cdb == NULL)
cffi_closure_free(closure);
else
- Py_DECREF(cd);
+ Py_DECREF(cdb);
return NULL;
}
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -770,3 +770,12 @@
BStruct = new_struct_type("foo")
complete_struct_or_union(BStruct, [('a1', BInt, 1)])
py.test.raises(NotImplementedError, newp, new_pointer_type(BStruct), [-1])
+
+def test_weakref():
+ import weakref
+ BInt = new_primitive_type("int")
+ BPtr = new_pointer_type(BInt)
+ weakref.ref(BInt)
+ weakref.ref(newp(BPtr, 42))
+ py.test.raises(TypeError, weakref.ref, cast(BPtr, 42))
+ py.test.raises(TypeError, weakref.ref, cast(BInt, 42))
More information about the pypy-commit
mailing list