Commit 1f1e25b2 authored by Thomas Heller's avatar Thomas Heller

Convert the internal ctypes array type cache to a WeakValueDict so

that array types do not live longer than needed.
parent eb758cdc
...@@ -116,5 +116,19 @@ class ArrayTestCase(unittest.TestCase): ...@@ -116,5 +116,19 @@ class ArrayTestCase(unittest.TestCase):
self.failUnlessEqual(sz[1:4:2], "o") self.failUnlessEqual(sz[1:4:2], "o")
self.failUnlessEqual(sz.value, "foo") self.failUnlessEqual(sz.value, "foo")
def test_cache(self):
# Array types are cached internally in the _ctypes extension,
# in a WeakValueDictionary. Make sure the array type is
# removed from the cache when the itemtype goes away. This
# test will not fail, but will show a leak in the testsuite.
# Create a new type:
class my_int(c_int):
pass
# Create a new array type based on it:
t1 = my_int * 1
t2 = my_int * 1
self.failUnless(t1 is t2)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -364,6 +364,9 @@ Core and builtins ...@@ -364,6 +364,9 @@ Core and builtins
Library Library
------- -------
- Convert the internal ctypes array type cache to a WeakValueDict so
that array types do not live longer than needed.
- Issue #1786: pdb should use its own stdin/stdout around an exec call - Issue #1786: pdb should use its own stdin/stdout around an exec call
and when creating a recursive instance. and when creating a recursive instance.
......
...@@ -127,6 +127,7 @@ bytes(cdata) ...@@ -127,6 +127,7 @@ bytes(cdata)
PyObject *PyExc_ArgError; PyObject *PyExc_ArgError;
static PyTypeObject Simple_Type; static PyTypeObject Simple_Type;
PyObject *array_types_cache;
char *conversion_mode_encoding = NULL; char *conversion_mode_encoding = NULL;
char *conversion_mode_errors = NULL; char *conversion_mode_errors = NULL;
...@@ -4086,16 +4087,10 @@ PyTypeObject Array_Type = { ...@@ -4086,16 +4087,10 @@ PyTypeObject Array_Type = {
PyObject * PyObject *
CreateArrayType(PyObject *itemtype, Py_ssize_t length) CreateArrayType(PyObject *itemtype, Py_ssize_t length)
{ {
static PyObject *cache;
PyObject *key; PyObject *key;
PyObject *result; PyObject *result;
char name[256]; char name[256];
if (cache == NULL) {
cache = PyDict_New();
if (cache == NULL)
return NULL;
}
#if (PY_VERSION_HEX < 0x02050000) #if (PY_VERSION_HEX < 0x02050000)
key = Py_BuildValue("(Oi)", itemtype, length); key = Py_BuildValue("(Oi)", itemtype, length);
#else #else
...@@ -4103,12 +4098,12 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length) ...@@ -4103,12 +4098,12 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length)
#endif #endif
if (!key) if (!key)
return NULL; return NULL;
result = PyDict_GetItem(cache, key); result = PyObject_GetItem(array_types_cache, key);
if (result) { if (result) {
Py_INCREF(result);
Py_DECREF(key); Py_DECREF(key);
return result; return result;
} } else
PyErr_Clear();
if (!PyType_Check(itemtype)) { if (!PyType_Check(itemtype)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
...@@ -4138,7 +4133,11 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length) ...@@ -4138,7 +4133,11 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length)
); );
if (!result) if (!result)
return NULL; return NULL;
PyDict_SetItem(cache, key, result); if (-1 == PyObject_SetItem(array_types_cache, key, result)) {
Py_DECREF(key);
Py_DECREF(result);
return NULL;
}
Py_DECREF(key); Py_DECREF(key);
return result; return result;
} }
...@@ -4951,6 +4950,7 @@ PyMODINIT_FUNC ...@@ -4951,6 +4950,7 @@ PyMODINIT_FUNC
init_ctypes(void) init_ctypes(void)
{ {
PyObject *m; PyObject *m;
PyObject *weakref;
/* Note: /* Note:
ob_type is the metatype (the 'type'), defaults to PyType_Type, ob_type is the metatype (the 'type'), defaults to PyType_Type,
...@@ -4963,6 +4963,16 @@ init_ctypes(void) ...@@ -4963,6 +4963,16 @@ init_ctypes(void)
if (!m) if (!m)
return; return;
weakref = PyImport_ImportModule("weakref");
if (weakref == NULL)
return;
array_types_cache = PyObject_CallMethod(weakref,
"WeakValueDictionary",
NULL);
if (array_types_cache == NULL)
return;
Py_DECREF(weakref);
if (PyType_Ready(&PyCArg_Type) < 0) if (PyType_Ready(&PyCArg_Type) < 0)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment