@@ -26,7 +26,7 @@ typedef struct _functools_state {
26
26
/* this object is used delimit args and keywords in the cache keys */
27
27
PyObject * kwd_mark ;
28
28
PyTypeObject * placeholder_type ;
29
- PyObject * placeholder ;
29
+ PyObject * placeholder ; // strong reference (singleton)
30
30
PyTypeObject * partial_type ;
31
31
PyTypeObject * keyobject_type ;
32
32
PyTypeObject * lru_list_elem_type ;
@@ -76,13 +76,12 @@ static PyMethodDef placeholder_methods[] = {
76
76
};
77
77
78
78
static void
79
- placeholder_dealloc (PyObject * placeholder )
79
+ placeholder_dealloc (PyObject * self )
80
80
{
81
- /* This should never get called, but we also don't want to SEGV if
82
- * we accidentally decref Placeholder out of existence. Instead,
83
- * since Placeholder is an immortal object, re-set the reference count.
84
- */
85
- _Py_SetImmortal (placeholder );
81
+ PyObject_GC_UnTrack (self );
82
+ PyTypeObject * tp = Py_TYPE (self );
83
+ tp -> tp_free ((PyObject * )self );
84
+ Py_DECREF (tp );
86
85
}
87
86
88
87
static PyObject *
@@ -93,10 +92,26 @@ placeholder_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
93
92
return NULL ;
94
93
}
95
94
_functools_state * state = get_functools_state_by_type (type );
95
+ if (state -> placeholder != NULL ) {
96
+ return Py_NewRef (state -> placeholder );
97
+ }
98
+
99
+ PyObject * placeholder = PyType_GenericNew (type , NULL , NULL );
100
+ if (placeholder == NULL ) {
101
+ return NULL ;
102
+ }
103
+
96
104
if (state -> placeholder == NULL ) {
97
- state -> placeholder = PyType_GenericNew ( type , NULL , NULL );
105
+ state -> placeholder = Py_NewRef ( placeholder );
98
106
}
99
- return state -> placeholder ;
107
+ return placeholder ;
108
+ }
109
+
110
+ static int
111
+ placeholder_traverse (PyObject * self , visitproc visit , void * arg )
112
+ {
113
+ Py_VISIT (Py_TYPE (self ));
114
+ return 0 ;
100
115
}
101
116
102
117
static PyType_Slot placeholder_type_slots [] = {
@@ -105,13 +120,14 @@ static PyType_Slot placeholder_type_slots[] = {
105
120
{Py_tp_doc , (void * )placeholder_doc },
106
121
{Py_tp_methods , placeholder_methods },
107
122
{Py_tp_new , placeholder_new },
123
+ {Py_tp_traverse , placeholder_traverse },
108
124
{0 , 0 }
109
125
};
110
126
111
127
static PyType_Spec placeholder_type_spec = {
112
128
.name = "functools._PlaceholderType" ,
113
129
.basicsize = sizeof (placeholderobject ),
114
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE ,
130
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC ,
115
131
.slots = placeholder_type_slots
116
132
};
117
133
@@ -1717,13 +1733,17 @@ _functools_exec(PyObject *module)
1717
1733
if (PyModule_AddType (module , state -> placeholder_type ) < 0 ) {
1718
1734
return -1 ;
1719
1735
}
1720
- state -> placeholder = PyObject_CallNoArgs ((PyObject * )state -> placeholder_type );
1721
- if (state -> placeholder == NULL ) {
1736
+
1737
+ PyObject * placeholder = PyObject_CallNoArgs ((PyObject * )state -> placeholder_type );
1738
+ if (placeholder == NULL ) {
1722
1739
return -1 ;
1723
1740
}
1724
- if (PyModule_AddObject (module , "Placeholder" , state -> placeholder ) < 0 ) {
1741
+ if (PyModule_AddObjectRef (module , "Placeholder" , placeholder ) < 0 ) {
1742
+ Py_DECREF (placeholder );
1725
1743
return -1 ;
1726
1744
}
1745
+ Py_DECREF (placeholder );
1746
+
1727
1747
state -> partial_type = (PyTypeObject * )PyType_FromModuleAndSpec (module ,
1728
1748
& partial_type_spec , NULL );
1729
1749
if (state -> partial_type == NULL ) {
@@ -1769,6 +1789,7 @@ _functools_traverse(PyObject *module, visitproc visit, void *arg)
1769
1789
_functools_state * state = get_functools_state (module );
1770
1790
Py_VISIT (state -> kwd_mark );
1771
1791
Py_VISIT (state -> placeholder_type );
1792
+ Py_VISIT (state -> placeholder );
1772
1793
Py_VISIT (state -> partial_type );
1773
1794
Py_VISIT (state -> keyobject_type );
1774
1795
Py_VISIT (state -> lru_list_elem_type );
@@ -1781,6 +1802,7 @@ _functools_clear(PyObject *module)
1781
1802
_functools_state * state = get_functools_state (module );
1782
1803
Py_CLEAR (state -> kwd_mark );
1783
1804
Py_CLEAR (state -> placeholder_type );
1805
+ Py_CLEAR (state -> placeholder );
1784
1806
Py_CLEAR (state -> partial_type );
1785
1807
Py_CLEAR (state -> keyobject_type );
1786
1808
Py_CLEAR (state -> lru_list_elem_type );
0 commit comments