In most normal cases, you do not need to do tracking / tracking yourself. This is described in the documentation, but this is not done clearly. In the case of the Noddy example, you definitely do not.
The short option is that TypeObject contains two function pointers: tp_alloc and tp_free . By default, tp_alloc calls all the correct functions when creating the class (if Py_TPFLAGS_HAVE_GC set), and tp_free does not check the class when it is destroyed.
Noddy documentation says (at the end of the section):
This is pretty much the case. If we wrote custom tp_alloc or tp_free , you must change them to collect circular garbage. Most extensions will use the provided versions automatically.
Unfortunately, one place that makes it hard to understand that you donβt need to do this is the circular garbage collection documentation .
detail:
Nodds are allocated using the Noddy_new function placed in tp_new slots. According to the documentation , the main thing that the βnewβ function should execute is to call tp_alloc . Usually you do not write tp_alloc yourself, but by default PyType_GenericAlloc() .
Looking at PyType_GenericAlloc() in a Python source , a series of sections are displayed where it changes based on PyType_IS_GC(type) . First it calls _PyObject_GC_Malloc instead of PyObject_Malloc , and then it calls _PyObject_GC_TRACK(obj) . [Note that all PyObject_New really does is call PyObject_Malloc and then tp_init .]
Similarly, upon release, you call tp_free slot , which is automatically set to PyObject_GC_Del for classes with Py_TPFLAGS_HAVE_GC . PyObject_GC_Del contains code that does the same thing as PyObject_GC_UnTrack , so a call to check is not needed.
source share