@@ -617,7 +617,7 @@ static PyObject *
617617_zstd_ZstdDecompressor_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
618618{
619619 ZstdDecompressor * self ;
620- self = (ZstdDecompressor * ) type -> tp_alloc ( type , 0 );
620+ self = PyObject_GC_New (ZstdDecompressor , type );
621621 if (self == NULL ) {
622622 goto error ;
623623 }
@@ -642,28 +642,31 @@ _zstd_ZstdDecompressor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
642642 return (PyObject * )self ;
643643
644644error :
645- Py_XDECREF (self );
645+ PyObject_GC_UnTrack (self );
646646 return NULL ;
647647}
648648
649649static void
650650ZstdDecompressor_dealloc (PyObject * ob )
651651{
652652 ZstdDecompressor * self = ZstdDecompressor_CAST (ob );
653+
654+ PyObject_GC_UnTrack (self );
655+
653656 /* Free decompression context */
654657 ZSTD_freeDCtx (self -> dctx );
655658
656- /* Py_XDECREF the dict after free decompression context */
657- Py_XDECREF (self -> dict );
659+ /* Py_CLEAR the dict after free decompression context */
660+ Py_CLEAR (self -> dict );
658661
659662 /* Free unconsumed input data buffer */
660663 PyMem_Free (self -> input_buffer );
661664
662665 /* Free unused data */
663- Py_XDECREF (self -> unused_data );
666+ Py_CLEAR (self -> unused_data );
664667
665668 PyTypeObject * tp = Py_TYPE (self );
666- tp -> tp_free (( PyObject * ) self );
669+ PyObject_GC_Del ( ob );
667670 Py_DECREF (tp );
668671}
669672
@@ -711,6 +714,8 @@ _zstd_ZstdDecompressor___init___impl(ZstdDecompressor *self,
711714 }
712715 }
713716
717+ // We can only start tracking self with the GC once self->dict is set.
718+ PyObject_GC_Track (self );
714719 return 0 ;
715720}
716721
@@ -837,6 +842,23 @@ static PyGetSetDef ZstdDecompressor_getset[] = {
837842 {0 }
838843};
839844
845+ static int
846+ ZstdDecompressor_traverse (PyObject * ob , visitproc visit , void * arg )
847+ {
848+ ZstdDecompressor * self = ZstdDecompressor_CAST (ob );
849+ Py_VISIT (self -> dict );
850+ return 0 ;
851+ }
852+
853+ static int
854+ ZstdDecompressor_clear (PyObject * ob )
855+ {
856+ ZstdDecompressor * self = ZstdDecompressor_CAST (ob );
857+ Py_CLEAR (self -> dict );
858+ Py_CLEAR (self -> unused_data );
859+ return 0 ;
860+ }
861+
840862static PyType_Slot ZstdDecompressor_slots [] = {
841863 {Py_tp_new , _zstd_ZstdDecompressor_new },
842864 {Py_tp_dealloc , ZstdDecompressor_dealloc },
@@ -845,12 +867,14 @@ static PyType_Slot ZstdDecompressor_slots[] = {
845867 {Py_tp_members , ZstdDecompressor_members },
846868 {Py_tp_getset , ZstdDecompressor_getset },
847869 {Py_tp_doc , (char * )_zstd_ZstdDecompressor___init____doc__ },
870+ {Py_tp_traverse , ZstdDecompressor_traverse },
871+ {Py_tp_clear , ZstdDecompressor_clear },
848872 {0 }
849873};
850874
851875PyType_Spec ZstdDecompressor_type_spec = {
852876 .name = "_zstd.ZstdDecompressor" ,
853877 .basicsize = sizeof (ZstdDecompressor ),
854- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
878+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
855879 .slots = ZstdDecompressor_slots ,
856880};
0 commit comments