@@ -762,10 +762,28 @@ typedef struct lru_list_elem {
762762 PyObject * key , * result ;
763763} lru_list_elem ;
764764
765+ static int
766+ lru_list_elem_clear (lru_list_elem * link )
767+ {
768+ Py_CLEAR (link -> key );
769+ Py_CLEAR (link -> result );
770+ return 0 ;
771+ }
772+
773+ static int
774+ lru_list_elem_traverse (lru_list_elem * link , visitproc visit , void * arg )
775+ {
776+ Py_VISIT (link -> key );
777+ Py_VISIT (link -> result );
778+ Py_VISIT (Py_TYPE (link ));
779+ return 0 ;
780+ }
781+
765782static void
766783lru_list_elem_dealloc (lru_list_elem * link )
767784{
768785 PyTypeObject * tp = Py_TYPE (link );
786+ PyObject_GC_UnTrack (link );
769787 Py_XDECREF (link -> key );
770788 Py_XDECREF (link -> result );
771789 tp -> tp_free (link );
@@ -774,13 +792,16 @@ lru_list_elem_dealloc(lru_list_elem *link)
774792
775793static PyType_Slot lru_list_elem_type_slots [] = {
776794 {Py_tp_dealloc , lru_list_elem_dealloc },
795+ {Py_tp_traverse , lru_list_elem_traverse },
796+ {Py_tp_clear , lru_list_elem_clear },
777797 {0 , 0 }
778798};
779799
780800static PyType_Spec lru_list_elem_type_spec = {
781801 .name = "functools._lru_list_elem" ,
782802 .basicsize = sizeof (lru_list_elem ),
783- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION ,
803+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
804+ Py_TPFLAGS_HAVE_GC ),
784805 .slots = lru_list_elem_type_slots
785806};
786807
@@ -1045,8 +1066,8 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
10451066 self -> root .next == & self -> root )
10461067 {
10471068 /* Cache is not full, so put the result in a new link */
1048- link = (lru_list_elem * )PyObject_New (lru_list_elem ,
1049- self -> lru_list_elem_type );
1069+ link = (lru_list_elem * )PyObject_GC_New (lru_list_elem ,
1070+ self -> lru_list_elem_type );
10501071 if (link == NULL ) {
10511072 Py_DECREF (key );
10521073 Py_DECREF (result );
@@ -1056,6 +1077,7 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
10561077 link -> hash = hash ;
10571078 link -> key = key ;
10581079 link -> result = result ;
1080+ PyObject_GC_Track (link );
10591081 /* What is really needed here is a SetItem variant with a "no clobber"
10601082 option. If the __eq__ call triggers a reentrant call that adds
10611083 this same key, then this setitem call will update the cache dict
@@ -1345,9 +1367,7 @@ lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
13451367 lru_list_elem * link = self -> root .next ;
13461368 while (link != & self -> root ) {
13471369 lru_list_elem * next = link -> next ;
1348- Py_VISIT (link -> key );
1349- Py_VISIT (link -> result );
1350- Py_VISIT (Py_TYPE (link ));
1370+ Py_VISIT (link );
13511371 link = next ;
13521372 }
13531373 Py_VISIT (self -> cache );
0 commit comments