Author: Armin Rigo <[email protected]>
Branch:
Changeset: r1121:00f0e57fce9a
Date: 2013-01-10 10:01 +0100
http://bitbucket.org/cffi/cffi/changeset/00f0e57fce9a/
Log: minibuffer: weakref support, and keep alive the argument.
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4485,7 +4485,7 @@
return NULL;
}
/*WRITE(cd->c_data, size)*/
- return minibuffer_new(cd->c_data, size);
+ return minibuffer_new(cd->c_data, size, (PyObject *)cd);
}
static PyObject *b_get_errno(PyObject *self, PyObject *noarg)
diff --git a/c/minibuffer.h b/c/minibuffer.h
--- a/c/minibuffer.h
+++ b/c/minibuffer.h
@@ -9,6 +9,8 @@
PyObject_HEAD
char *mb_data;
Py_ssize_t mb_size;
+ PyObject *mb_keepalive;
+ PyObject *mb_weakreflist; /* weakref support */
} MiniBufferObj;
static Py_ssize_t mb_length(MiniBufferObj *self)
@@ -120,6 +122,30 @@
(releasebufferproc)0,
};
+static void
+mb_dealloc(MiniBufferObj *ob)
+{
+ PyObject_GC_UnTrack(ob);
+ if (ob->mb_weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *)ob);
+ Py_XDECREF(ob->mb_keepalive);
+ Py_TYPE(ob)->tp_free((PyObject *)ob);
+}
+
+static int
+mb_traverse(MiniBufferObj *ob, visitproc visit, void *arg)
+{
+ Py_VISIT(ob->mb_keepalive);
+ return 0;
+}
+
+static int
+mb_clear(MiniBufferObj *ob)
+{
+ Py_CLEAR(ob->mb_keepalive);
+ return 0;
+}
+
#if PY_MAJOR_VERSION >= 3
/* pfffffffffffff pages of copy-paste from listobject.c */
static PyObject *mb_subscript(MiniBufferObj *self, PyObject *item)
@@ -198,9 +224,9 @@
#endif
#if PY_MAJOR_VERSION >= 3
-# define MINIBUF_TPFLAGS (Py_TPFLAGS_DEFAULT)
+# define MINIBUF_TPFLAGS 0
#else
-# define MINIBUF_TPFLAGS (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER |
Py_TPFLAGS_HAVE_NEWBUFFER)
+# define MINIBUF_TPFLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER |
Py_TPFLAGS_HAVE_NEWBUFFER)
#endif
static PyTypeObject MiniBuffer_Type = {
@@ -208,7 +234,7 @@
"_cffi_backend.buffer",
sizeof(MiniBufferObj),
0,
- (destructor)PyObject_Del, /* tp_dealloc */
+ (destructor)mb_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
@@ -227,15 +253,25 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
&mb_as_buffer, /* tp_as_buffer */
- MINIBUF_TPFLAGS, /* tp_flags */
+ (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ MINIBUF_TPFLAGS), /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)mb_traverse, /* tp_traverse */
+ (inquiry)mb_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(MiniBufferObj, mb_weakreflist), /* tp_weaklistoffset */
};
-static PyObject *minibuffer_new(char *data, Py_ssize_t size)
+static PyObject *minibuffer_new(char *data, Py_ssize_t size,
+ PyObject *keepalive)
{
- MiniBufferObj *ob = PyObject_New(MiniBufferObj, &MiniBuffer_Type);
+ MiniBufferObj *ob = PyObject_GC_New(MiniBufferObj, &MiniBuffer_Type);
if (ob != NULL) {
ob->mb_data = data;
ob->mb_size = size;
+ ob->mb_keepalive = keepalive; Py_INCREF(keepalive);
+ ob->mb_weakreflist = NULL;
+ PyObject_GC_Track(ob);
}
return (PyObject *)ob;
}
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -1446,10 +1446,16 @@
import _weakref
BInt = new_primitive_type("int")
BPtr = new_pointer_type(BInt)
- _weakref.ref(BInt)
- _weakref.ref(newp(BPtr, 42))
- _weakref.ref(cast(BPtr, 42))
- _weakref.ref(cast(BInt, 42))
+ rlist = [_weakref.ref(BInt),
+ _weakref.ref(newp(BPtr, 42)),
+ _weakref.ref(cast(BPtr, 42)),
+ _weakref.ref(cast(BInt, 42)),
+ _weakref.ref(buffer(newp(BPtr, 42))),
+ ]
+ for i in range(5):
+ import gc; gc.collect()
+ if [r() for r in rlist] == [None for r in rlist]:
+ break
def test_no_inheritance():
BInt = new_primitive_type("int")
@@ -2552,3 +2558,15 @@
BCharP = new_pointer_type(new_primitive_type("char"))
BCharArray = new_array_type(BCharP, None)
py.test.raises(TypeError, newp, BCharArray, u+'foobar')
+
+def test_buffer_keepalive():
+ BCharP = new_pointer_type(new_primitive_type("char"))
+ BCharArray = new_array_type(BCharP, None)
+ buflist = []
+ for i in range(20):
+ c = newp(BCharArray, b"hi there %d" % i)
+ buflist.append(buffer(c))
+ import gc; gc.collect()
+ for i in range(20):
+ buf = buflist[i]
+ assert buf[:] == b"hi there %d\x00" % i
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit