Skip to content

Commit 84f832f

Browse files
committed
fully implement GC protocol for _tkinter objects
1 parent 2a54acf commit 84f832f

File tree

1 file changed

+81
-32
lines changed

1 file changed

+81
-32
lines changed

Modules/_tkinter.c

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -589,10 +589,14 @@ Tkapp_New(const char *screenName, const char *className,
589589
int interactive, int wantobjects, int wantTk, int sync,
590590
const char *use)
591591
{
592+
PyTypeObject *type;
592593
TkappObject *v;
593594
char *argv0;
594595

595-
v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
596+
type = (PyTypeObject *)Tkapp_Type;
597+
assert(type != NULL);
598+
assert(type->tp_alloc != NULL);
599+
v = (TkappObject *)type->tp_alloc(type, 0);
596600
if (v == NULL)
597601
return NULL;
598602

@@ -788,8 +792,13 @@ static PyObject *PyTclObject_Type;
788792
static PyObject *
789793
newPyTclObject(Tcl_Obj *arg)
790794
{
795+
PyTypeObject *type;
791796
PyTclObject *self;
792-
self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
797+
798+
type = (PyTypeObject *)PyTclObject_Type;
799+
assert(type != NULL);
800+
assert(type->tp_alloc != NULL);
801+
self = (PyTclObject *)type->tp_alloc(type, 0);
793802
if (self == NULL)
794803
return NULL;
795804
Tcl_IncrRefCount(arg);
@@ -799,16 +808,24 @@ newPyTclObject(Tcl_Obj *arg)
799808
}
800809

801810
static void
802-
PyTclObject_dealloc(PyObject *_self)
811+
PyTclObject_dealloc(PyObject *op)
803812
{
804-
PyTclObject *self = PyTclObject_CAST(_self);
805-
PyObject *tp = (PyObject *) Py_TYPE(self);
813+
PyTypeObject *tp = Py_TYPE(op);
814+
PyObject_GC_UnTrack(op);
815+
PyTclObject *self = PyTclObject_CAST(op);
806816
Tcl_DecrRefCount(self->value);
807817
Py_XDECREF(self->string);
808-
PyObject_Free(self);
818+
tp->tp_free(self);
809819
Py_DECREF(tp);
810820
}
811821

822+
static int
823+
PyTclObject_traverse(PyObject *op, visitproc visit, void *arg)
824+
{
825+
Py_VISIT(Py_TYPE(op));
826+
return 0;
827+
}
828+
812829
/* Like _str, but create Unicode if necessary. */
813830
PyDoc_STRVAR(PyTclObject_string__doc__,
814831
"the string representation of this object, either as str or bytes");
@@ -897,6 +914,7 @@ static PyGetSetDef PyTclObject_getsetlist[] = {
897914

898915
static PyType_Slot PyTclObject_Type_slots[] = {
899916
{Py_tp_dealloc, PyTclObject_dealloc},
917+
{Py_tp_traverse, PyTclObject_traverse},
900918
{Py_tp_repr, PyTclObject_repr},
901919
{Py_tp_str, PyTclObject_str},
902920
{Py_tp_getattro, PyObject_GenericGetAttr},
@@ -906,11 +924,14 @@ static PyType_Slot PyTclObject_Type_slots[] = {
906924
};
907925

908926
static PyType_Spec PyTclObject_Type_spec = {
909-
"_tkinter.Tcl_Obj",
910-
sizeof(PyTclObject),
911-
0,
912-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
913-
PyTclObject_Type_slots,
927+
.name = "_tkinter.Tcl_Obj",
928+
.basicsize = sizeof(PyTclObject),
929+
.flags = (
930+
Py_TPFLAGS_DEFAULT
931+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
932+
| Py_TPFLAGS_HAVE_GC
933+
),
934+
.slots = PyTclObject_Type_slots,
914935
};
915936

916937

@@ -2742,9 +2763,13 @@ _tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
27422763
static TkttObject *
27432764
Tktt_New(PyObject *func)
27442765
{
2766+
PyTypeObject *type;
27452767
TkttObject *v;
27462768

2747-
v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
2769+
type = (PyTypeObject *)Tktt_Type;
2770+
assert(type != NULL);
2771+
assert(type->tp_alloc != NULL);
2772+
v = (TkttObject *)type->tp_alloc(type, 0);
27482773
if (v == NULL)
27492774
return NULL;
27502775

@@ -2756,18 +2781,25 @@ Tktt_New(PyObject *func)
27562781
}
27572782

27582783
static void
2759-
Tktt_Dealloc(PyObject *self)
2784+
Tktt_Dealloc(PyObject *op)
27602785
{
2761-
TkttObject *v = TkttObject_CAST(self);
2762-
PyObject *func = v->func;
2763-
PyObject *tp = (PyObject *) Py_TYPE(self);
2764-
2765-
Py_XDECREF(func);
2766-
2767-
PyObject_Free(self);
2786+
PyTypeObject *tp = Py_TYPE(op);
2787+
PyObject_GC_UnTrack(op);
2788+
TkttObject *self = TkttObject_CAST(op);
2789+
Py_XDECREF(self->func);
2790+
tp->tp_free(self);
27682791
Py_DECREF(tp);
27692792
}
27702793

2794+
static int
2795+
Tktt_Traverse(PyObject *op, visitproc visit, void *arg)
2796+
{
2797+
TkttObject *self = TkttObject_CAST(op);
2798+
Py_VISIT(Py_TYPE(op));
2799+
Py_VISIT(self->func);
2800+
return 0;
2801+
}
2802+
27712803
static PyObject *
27722804
Tktt_Repr(PyObject *self)
27732805
{
@@ -3061,18 +3093,27 @@ _tkinter_tkapp_willdispatch_impl(TkappObject *self)
30613093
static void
30623094
Tkapp_Dealloc(PyObject *op)
30633095
{
3096+
PyTypeObject *tp = Py_TYPE(op);
3097+
PyObject_GC_UnTrack(op);
30643098
TkappObject *self = TkappObject_CAST(op);
3065-
PyTypeObject *tp = Py_TYPE(self);
30663099
/*CHECK_TCL_APPARTMENT;*/
30673100
ENTER_TCL
30683101
Tcl_DeleteInterp(Tkapp_Interp(self));
30693102
LEAVE_TCL
30703103
Py_XDECREF(self->trace);
3071-
PyObject_Free(self);
3104+
tp->tp_free(self);
30723105
Py_DECREF(tp);
30733106
DisableEventHook();
30743107
}
30753108

3109+
static int
3110+
Tkapp_Traverse(PyObject *op, visitproc visit, void *arg)
3111+
{
3112+
TkappObject *self = TkappObject_CAST(op);
3113+
Py_VISIT(Py_TYPE(op));
3114+
Py_VISIT(self->trace);
3115+
return 0;
3116+
}
30763117

30773118

30783119
/**** Tkinter Module ****/
@@ -3261,17 +3302,21 @@ static PyMethodDef Tktt_methods[] =
32613302

32623303
static PyType_Slot Tktt_Type_slots[] = {
32633304
{Py_tp_dealloc, Tktt_Dealloc},
3305+
{Py_tp_traverse, Tktt_Traverse},
32643306
{Py_tp_repr, Tktt_Repr},
32653307
{Py_tp_methods, Tktt_methods},
32663308
{0, 0}
32673309
};
32683310

32693311
static PyType_Spec Tktt_Type_spec = {
3270-
"_tkinter.tktimertoken",
3271-
sizeof(TkttObject),
3272-
0,
3273-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3274-
Tktt_Type_slots,
3312+
.name = "_tkinter.tktimertoken",
3313+
.basicsize = sizeof(TkttObject),
3314+
.flags = (
3315+
Py_TPFLAGS_DEFAULT
3316+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
3317+
| Py_TPFLAGS_HAVE_GC
3318+
),
3319+
.slots = Tktt_Type_slots,
32753320
};
32763321

32773322

@@ -3317,17 +3362,21 @@ static PyMethodDef Tkapp_methods[] =
33173362

33183363
static PyType_Slot Tkapp_Type_slots[] = {
33193364
{Py_tp_dealloc, Tkapp_Dealloc},
3365+
{Py_tp_traverse, Tkapp_Traverse},
33203366
{Py_tp_methods, Tkapp_methods},
33213367
{0, 0}
33223368
};
33233369

33243370

33253371
static PyType_Spec Tkapp_Type_spec = {
3326-
"_tkinter.tkapp",
3327-
sizeof(TkappObject),
3328-
0,
3329-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3330-
Tkapp_Type_slots,
3372+
.name = "_tkinter.tkapp",
3373+
.basicsize = sizeof(TkappObject),
3374+
.flags = (
3375+
Py_TPFLAGS_DEFAULT
3376+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
3377+
| Py_TPFLAGS_HAVE_GC
3378+
),
3379+
.slots = Tkapp_Type_slots,
33313380
};
33323381

33333382
static PyMethodDef moduleMethods[] =

0 commit comments

Comments
 (0)