diff options
author | Raymond Hettinger <python@rcn.com> | 2005-06-19 05:53:15 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2005-06-19 05:53:15 (GMT) |
commit | 8f7dce605fefb605da4c732bdaffd01e5246362a (patch) | |
tree | 68404535b628089518b4b659468bc97eda9c23df | |
parent | d1d13eb9725c7333b5c9cbc62d9f39771422c781 (diff) | |
download | cpython-8f7dce605fefb605da4c732bdaffd01e5246362a.zip cpython-8f7dce605fefb605da4c732bdaffd01e5246362a.tar.gz cpython-8f7dce605fefb605da4c732bdaffd01e5246362a.tar.bz2 |
SF patch #1200018: Restore GC support to set objects
Reverts 1.26 and 1.27.
And adds cycle testing.
-rw-r--r-- | Lib/test/test_set.py | 10 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Objects/setobject.c | 31 |
3 files changed, 36 insertions, 7 deletions
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 900d8e4..26e38ab 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -202,6 +202,16 @@ class TestJointOps(unittest.TestCase): self.assertNotEqual(id(t), id(newt)) self.assertEqual(t.value + 1, newt.value) + def test_gc(self): + # Create a nest of cycles to exercise overall ref count check + class A: + pass + s = set(A() for i in xrange(1000)) + for elem in s: + elem.cycle = s + elem.sub = elem + elem.set = set([elem]) + class TestSet(TestJointOps): thetype = set @@ -12,6 +12,8 @@ What's New in Python 2.4.2a Core and builtins ----------------- +- Fix garbage collection for set and frozenset objects. SF patch #1200018. + - It is now safe to call PyGILState_Release() before PyEval_InitThreads() (note that if there is reason to believe there are multiple threads around you still must call PyEval_InitThreads() diff --git a/Objects/setobject.c b/Objects/setobject.c index 8ef671e..f9448c9 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -114,12 +114,21 @@ frozenset_dict_wrapper(PyObject *d) static void set_dealloc(PySetObject *so) { + PyObject_GC_UnTrack(so); if (so->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) so); Py_XDECREF(so->data); so->ob_type->tp_free(so); } +static int +set_traverse(PySetObject *so, visitproc visit, void *arg) +{ + if (so->data) + return visit(so->data, arg); + return 0; +} + static PyObject * set_iter(PySetObject *so) { @@ -757,6 +766,14 @@ set_clear(PySetObject *so) PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); +static int +set_tp_clear(PySetObject *so) +{ + PyDict_Clear(so->data); + so->hash = -1; + return 0; +} + static PyObject * set_add(PySetObject *so, PyObject *item) { @@ -1007,11 +1024,11 @@ PyTypeObject PySet_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ set_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)set_traverse, /* tp_traverse */ + (inquiry)set_tp_clear, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ (getiterfunc)set_iter, /* tp_iter */ @@ -1027,7 +1044,7 @@ PyTypeObject PySet_Type = { (initproc)set_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ set_new, /* tp_new */ - PyObject_Del, /* tp_free */ + PyObject_GC_Del, /* tp_free */ }; /* frozenset object ********************************************************/ @@ -1102,10 +1119,10 @@ PyTypeObject PyFrozenSet_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ frozenset_doc, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)set_traverse, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ @@ -1122,5 +1139,5 @@ PyTypeObject PyFrozenSet_Type = { 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ frozenset_new, /* tp_new */ - PyObject_Del, /* tp_free */ + PyObject_GC_Del, /* tp_free */ }; |