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