@@ -337,12 +337,44 @@ That is, heap types should:
337337- Define a traverse function using ``Py_tp_traverse ``, which
338338 visits the type (e.g. using :c:expr: `Py_VISIT(Py_TYPE(self)) `).
339339
340- Please refer to the :ref: ` the documentation < type-structs >` of
340+ Please refer to the the documentation of
341341:c:macro: `Py_TPFLAGS_HAVE_GC ` and :c:member: `~PyTypeObject.tp_traverse `
342342for additional considerations.
343343
344- If your traverse function delegates to the ``tp_traverse `` of its base class
345- (or another type), ensure that ``Py_TYPE(self) `` is visited only once.
344+ The API for defining heap types grew organically, leaving it
345+ somewhat awkward to use in its current state.
346+ The following sections will guide you through common issues.
347+
348+
349+ ``tp_traverse `` in Python 3.8 and lower
350+ .......................................
351+
352+ The requirement to visit the type from ``tp_traverse `` was added in Python 3.9.
353+ If you support Python 3.8 and lower, the traverse function must *not *
354+ visit the type, so it must be more complicated::
355+
356+ static int my_traverse(PyObject *self, visitproc visit, void *arg)
357+ {
358+ if (Py_Version >= 0x03090000) {
359+ Py_VISIT(Py_TYPE(self));
360+ }
361+ return 0;
362+ }
363+
364+ Unfortunately, :c:data: `Py_Version ` was only added in Python 3.11.
365+ As a replacement, use:
366+
367+ * :c:macro: `PY_VERSION_HEX `, if not using the stable ABI, or
368+ * :py:data: `sys.version_info ` (via :c:func: `PySys_GetObject ` and
369+ :c:func: `PyArg_ParseTuple `).
370+
371+
372+ Delegating ``tp_traverse ``
373+ ..........................
374+
375+ If your traverse function delegates to the :c:member: `~PyTypeObject.tp_traverse `
376+ of its base class (or another type), ensure that ``Py_TYPE(self) `` is visited
377+ only once.
346378Note that only heap type are expected to visit the type in ``tp_traverse ``.
347379
348380For example, if your traverse function includes::
@@ -354,11 +386,70 @@ For example, if your traverse function includes::
354386 if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
355387 // a heap type's tp_traverse already visited Py_TYPE(self)
356388 } else {
357- Py_VISIT(Py_TYPE(self));
389+ if (Py_Version >= 0x03090000) {
390+ Py_VISIT(Py_TYPE(self));
391+ }
358392 }
359393
360- It is not necessary to handle the type's reference count in ``tp_new ``
361- and ``tp_clear ``.
394+ It is not necessary to handle the type's reference count in
395+ :c:member: `~PyTypeObject.tp_new ` and :c:member: `~PyTypeObject.tp_clear `.
396+
397+
398+ Defining ``tp_dealloc ``
399+ .......................
400+
401+ If your type has a custom :c:member: `~PyTypeObject.tp_dealloc ` function,
402+ it needs to:
403+
404+ - call :c:func: `PyObject_GC_UnTrack ` before any fields are invalidated, and
405+ - decrement the reference count of the type.
406+
407+ To keep the type valid while ``tp_free `` is called, the type's refcount needs
408+ to be decremented *after * the instance is deallocated. For example::
409+
410+ static void my_dealloc(PyObject *self)
411+ {
412+ PyObject_GC_UnTrack(self);
413+ ...
414+ PyTypeObject *type = Py_TYPE(self);
415+ type->tp_free(self);
416+ Py_DECREF(type);
417+ }
418+
419+ The default ``tp_dealloc `` function does this, so
420+ if your type does *not * override
421+ ``tp_dealloc `` you don't need to add it.
422+
423+
424+ Not overriding ``tp_free ``
425+ ..........................
426+
427+ The :c:member: `~PyTypeObject.tp_free ` slot of a heap type must be set to
428+ :c:func: `PyObject_GC_Del `.
429+ This is the default; do not override it.
430+
431+
432+ Avoiding ``PyObject_New ``
433+ .........................
434+
435+ GC-tracked objects need to be allocated using GC-aware functions.
436+
437+ If you use use :c:func: `PyObject_New ` or :c:func: `PyObject_NewVar `:
438+
439+ - Get and call type's :c:member: `~PyTypeObject.tp_alloc ` slot, if possible.
440+ That is, replace ``TYPE *o = PyObject_New(TYPE, typeobj) `` with::
441+
442+ TYPE *o = typeobj->tp_alloc(typeobj, 0);
443+
444+ Replace ``o = PyObject_NewVar(TYPE, typeobj, size) `` with the same,
445+ but use size instead of the 0.
446+
447+ - If the above is not possible (e.g. inside a custom ``tp_alloc ``),
448+ call :c:func: `PyObject_GC_New ` or :c:func: `PyObject_GC_NewVar `::
449+
450+ TYPE *o = PyObject_GC_New(TYPE, typeobj);
451+
452+ TYPE *o = PyObject_GC_NewVar(TYPE, typeobj, size);
362453
363454
364455Module State Access from Classes
0 commit comments