@@ -337,12 +337,44 @@ That is, heap types should:
337
337
- Define a traverse function using ``Py_tp_traverse ``, which
338
338
visits the type (e.g. using :c:expr: `Py_VISIT(Py_TYPE(self)) `).
339
339
340
- Please refer to the :ref: ` the documentation < type-structs >` of
340
+ Please refer to the the documentation of
341
341
:c:macro: `Py_TPFLAGS_HAVE_GC ` and :c:member: `~PyTypeObject.tp_traverse `
342
342
for additional considerations.
343
343
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.
346
378
Note that only heap type are expected to visit the type in ``tp_traverse ``.
347
379
348
380
For example, if your traverse function includes::
@@ -354,11 +386,70 @@ For example, if your traverse function includes::
354
386
if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
355
387
// a heap type's tp_traverse already visited Py_TYPE(self)
356
388
} else {
357
- Py_VISIT(Py_TYPE(self));
389
+ if (Py_Version >= 0x03090000) {
390
+ Py_VISIT(Py_TYPE(self));
391
+ }
358
392
}
359
393
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);
362
453
363
454
364
455
Module State Access from Classes
0 commit comments