summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2005-06-18 21:00:26 (GMT)
committerRaymond Hettinger <python@rcn.com>2005-06-18 21:00:26 (GMT)
commitbb999b5925ae65d19282c3781cdbb678f92c410f (patch)
tree72801517d3a84fe2b1620612142c9699d8bf564d
parentf33f5e9d6efc1948da0f1d780837cf23d465c344 (diff)
downloadcpython-bb999b5925ae65d19282c3781cdbb678f92c410f.zip
cpython-bb999b5925ae65d19282c3781cdbb678f92c410f.tar.gz
cpython-bb999b5925ae65d19282c3781cdbb678f92c410f.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.py10
-rw-r--r--Objects/setobject.c31
2 files changed, 34 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
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 */
};