]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
SF patch #1200018: Restore GC support to set objects
authorRaymond Hettinger <python@rcn.com>
Sun, 19 Jun 2005 05:53:15 +0000 (05:53 +0000)
committerRaymond Hettinger <python@rcn.com>
Sun, 19 Jun 2005 05:53:15 +0000 (05:53 +0000)
Reverts 1.26 and 1.27.
And adds cycle testing.

Lib/test/test_set.py
Misc/NEWS
Objects/setobject.c

index 900d8e42c1593e7c8e424d70c90052bd439a7857..26e38abb21fa7193dd533ff52ed2e2e9474aa6b2 100644 (file)
@@ -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
 
index 28b9c2a87fc8c898eb16971e0abb7cb55b7339f3..b4e626f59edf6926e1bbc529a1083b88814a28ef 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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()
index 8ef671e3aff6a6b6f4e96b752cc6c37715329845..f9448c960b33ab0aad84578ac092963701f46704 100644 (file)
@@ -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 */
 };