Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

gh-75459: Doc: C API: Improve object life cycle documentation #125962

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bc32398
gh-75459: Doc: C API: Improve object life cycle documentation
rhansen Oct 19, 2024
361eaca
gh-75459: Doc: Tell sphinx to run graphviz
rhansen Oct 25, 2024
b27bcca
add blurb
rhansen Oct 25, 2024
b42b58d
Revert "gh-75459: Doc: Tell sphinx to run graphviz"
rhansen Oct 25, 2024
7e571ae
delete "ref count == 0" node, link directly to `tp_dealloc`
rhansen Oct 26, 2024
97dc30c
Merge branch 'main' into docs
rhansen Nov 7, 2024
85e535a
significant rewrite to address review comments
rhansen Nov 7, 2024
ef979e6
fix warnings
rhansen Nov 7, 2024
f3863c4
tweak cyclic isolate definition
rhansen Nov 7, 2024
6a114f9
apply css to the svg to support dark theme
rhansen Nov 8, 2024
182c977
increase font size
rhansen Nov 8, 2024
7cd0cb5
attempt to make the svg accessible
rhansen Nov 8, 2024
e34e224
wrap at 79 chars
rhansen Nov 8, 2024
16a29ab
address review feedback, and other tweaks
rhansen Nov 9, 2024
018a3c4
be more precise about the finalized mark
rhansen Nov 21, 2024
442b7f2
add pdf support, improve epub support
rhansen Nov 21, 2024
5ed484a
address feedback, and other improvements
rhansen Nov 27, 2024
b7774ae
Merge in the main branch
encukou Mar 11, 2025
bb1a94f
Remove redundant notes added in GH-129850
encukou Mar 11, 2025
fd38fd4
Merge branch 'main' into docs
ZeroIntensity May 5, 2025
3573c79
Apply suggestions from code review
ZeroIntensity May 5, 2025
2633594
Update Doc/c-api/lifecycle.rst
ZeroIntensity May 5, 2025
c57574a
Mention tp_alloc()
ZeroIntensity May 5, 2025
878fd27
Avoid using 'do not'
ZeroIntensity May 5, 2025
1b96fad
Mention PyObject_CallFinalizerFromDealloc()
ZeroIntensity May 5, 2025
e8c6852
Add some clarifications about tp_finalize()
ZeroIntensity May 5, 2025
3408919
Say that tp_dealloc() must free.
ZeroIntensity May 5, 2025
b6023a3
Fix doctest.
ZeroIntensity May 5, 2025
da3593c
Apply suggestions from code review
ZeroIntensity May 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Apply suggestions from code review
Co-authored-by: Petr Viktorin <encukou@gmail.com>
  • Loading branch information
ZeroIntensity and encukou authored May 17, 2025
commit da3593ca400fe94fb8b247c029737979e8b75888
14 changes: 8 additions & 6 deletions 14 Doc/c-api/allocation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Allocating Objects on the Heap

In general, consider this function to be a low-level routine. Use
:c:member:`~PyTypeObject.tp_alloc` where possible.
For implementing :c:member:`!tp_alloc` for your type, prefer
:c:func:`PyType_GenericAlloc` or :c:func:`PyObject_New`.

.. note::

Expand All @@ -35,7 +37,7 @@ Allocating Objects on the Heap
This does everything :c:func:`PyObject_Init` does, and also initializes the
length information for a variable-size object.

.. warning::
.. note::

This function only initializes some of the object's memory. It does not
zero the rest.
Expand Down Expand Up @@ -63,15 +65,15 @@ Allocating Objects on the Heap
This cannot be used for objects with :c:macro:`Py_TPFLAGS_HAVE_GC` set in
:c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_New` instead.

Memory allocated by this function must be freed with :c:func:`PyObject_Free`
Memory allocated by this macro must be freed with :c:func:`PyObject_Free`
(usually called via the object's :c:member:`~PyTypeObject.tp_free` slot).

.. warning::
.. note::

The returned memory is not guaranteed to have been completely zeroed
before it was initialized.

.. warning::
.. note::

This macro does not construct a fully initialized object of the given
type; it merely allocates memory and prepares it for further
Expand Down Expand Up @@ -116,12 +118,12 @@ Allocating Objects on the Heap
Memory allocated by this function must be freed with :c:func:`PyObject_Free`
(usually called via the object's :c:member:`~PyTypeObject.tp_free` slot).

.. warning::
.. note::

The returned memory is not guaranteed to have been completely zeroed
before it was initialized.

.. warning::
.. note::

This macro does not construct a fully initialized object of the given
type; it merely allocates memory and prepares it for further
Expand Down
4 changes: 2 additions & 2 deletions 4 Doc/c-api/gcsupport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ rules:
:c:func:`PyType_GenericAlloc` is preferred over a custom function that
simply calls this macro.

Memory allocated by this function must be freed with
Memory allocated by this macro must be freed with
:c:func:`PyObject_GC_Del` (usually called via the object's
:c:member:`~PyTypeObject.tp_free` slot).

Expand All @@ -88,7 +88,7 @@ rules:
:c:func:`PyType_GenericAlloc` is preferred over a custom function that
simply calls this macro.

Memory allocated by this function must be freed with
Memory allocated by this macro must be freed with
:c:func:`PyObject_GC_Del` (usually called via the object's
:c:member:`~PyTypeObject.tp_free` slot).

Expand Down
4 changes: 2 additions & 2 deletions 4 Doc/c-api/lifecycle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ that must be true for *B* to occur after *A*.
* When the garbage collector discovers a :term:`cyclic isolate` and all of
the objects in the group have already been marked as *finalized*, the
garbage collector clears one or more of the uncleared objects in the group
(possibly concurrently, but with the :term:`GIL` held) by calling each's
(possibly concurrently) by calling each's
:c:member:`~PyTypeObject.tp_clear` function. This repeats as long as the
cyclic isolate still exists and not all of the objects have been cleared.

Expand Down Expand Up @@ -209,7 +209,7 @@ Unlike clearing, finalization is not a phase of destruction. A finalized
object must still behave properly by continuing to fulfill its design
contracts. An object's finalizer is allowed to execute arbitrary Python code,
and is even allowed to prevent the impending destruction by adding a reference.
The finalizer is only contemporaneously related to destruction---it runs just
The finalizer is only related to destruction by call order---if it runs, it runs
before destruction, which starts with :c:member:`~PyTypeObject.tp_clear` (if
called) and concludes with :c:member:`~PyTypeObject.tp_dealloc`.

Expand Down
53 changes: 23 additions & 30 deletions 53 Doc/c-api/typeobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -695,12 +695,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
(:c:member:`~PyTypeObject.tp_finalize`) or automatically cleared
(:c:member:`~PyTypeObject.tp_clear`).

.. warning::

The :c:member:`~PyTypeObject.tp_dealloc` function can be called from any
thread, although the :term:`GIL` will be held.

Python currently destroys an object immediately from :c:func:`Py_DECREF`
CPython currently destroys an object immediately from :c:func:`Py_DECREF`
when the new reference count is zero, but this may change in a future
version.

Expand Down Expand Up @@ -777,13 +772,13 @@ and :c:data:`PyType_Type` effectively act as defaults.)
PyErr_SetRaisedException(exc);
}

In a garbage collected Python, :c:member:`!tp_dealloc` may be called from
:c:member:`!tp_dealloc` may be called from
any Python thread, not just the thread which created the object (if the
object becomes part of a refcount cycle, that cycle might be collected by
a garbage collection on any thread). This is not a problem for Python
API calls, since the thread on which :c:member:`!tp_dealloc` is called
with an :term:`attached thread state`. However, if the object being
destroyed in turn destroys objects from some other C or C++ library, care
destroyed in turn destroys objects from some other C library, care
should be taken to ensure that destroying those objects on the thread
which called :c:member:`!tp_dealloc` will not violate any assumptions of
the library.
Expand Down Expand Up @@ -1191,9 +1186,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
must be allocated using :c:macro:`PyObject_GC_New` or
:c:func:`PyType_GenericAlloc` and deallocated (see
:c:member:`~PyTypeObject.tp_free`) using :c:func:`PyObject_GC_Del`. More
information in section :ref:`supporting-cycle-detection`. This bit also
implies that the GC-related fields :c:member:`~PyTypeObject.tp_traverse`
and :c:member:`~PyTypeObject.tp_clear` are present in the type object.
information in section :ref:`supporting-cycle-detection`.

**Inheritance:**

Expand Down Expand Up @@ -1530,10 +1523,10 @@ and :c:data:`PyType_Type` effectively act as defaults.)
heap-allocated superclass).
If they do not, the type object may not be garbage-collected.

.. warning::
.. note::

The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
thread, although the :term:`GIL` will be held.
thread.

.. versionchanged:: 3.9

Expand Down Expand Up @@ -1568,29 +1561,29 @@ and :c:data:`PyType_Type` effectively act as defaults.)
integers. However, it may be convenient to clear all references, and write
the type's :c:member:`~PyTypeObject.tp_dealloc` function to invoke
:c:member:`!tp_clear` to avoid code duplication. (Beware that
:c:member:`!tp_clear` might have already been called, but :c:func:`Py_CLEAR`
is idempotent so extra checks are usually unnecessary.)
:c:member:`!tp_clear` might have already been called. Prefer calling
idempotent functions like :c:func:`Py_CLEAR`.)

Any non-trivial cleanup should be performed in
:c:member:`~PyTypeObject.tp_finalize` instead of :c:member:`!tp_clear`.

.. warning::
.. note::

If :c:member:`!tp_clear` fails to break a reference cycle then the
objects in the :term:`cyclic isolate` may remain indefinitely
uncollectable ("leak"). See :data:`gc.garbage`.

.. warning::
.. note::

Referents (direct and indirect) might have already been cleared; they are
not guaranteed to be in a consistent state.

.. warning::
.. note::

The :c:member:`~PyTypeObject.tp_clear` function can be called from any
thread, although the :term:`GIL` will be held.
thread.

.. warning::
.. note::

An object is not guaranteed to be automatically cleared before its
destructor (:c:member:`~PyTypeObject.tp_dealloc`) is called.
Expand Down Expand Up @@ -1635,7 +1628,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
* Python will not automatically call :c:member:`!tp_clear` multiple times
concurrently.

Python currently only automatically clears objects as needed to break
CPython currently only automatically clears objects as needed to break
reference cycles in a :term:`cyclic isolate`, but future versions might
clear objects regularly before their destruction.

Expand Down Expand Up @@ -2078,11 +2071,11 @@ and :c:data:`PyType_Type` effectively act as defaults.)
Static subtypes inherit this slot, which will be
:c:func:`PyType_GenericAlloc` if inherited from :class:`object`.

Dynamic subtypes (created by a class statement) do not inherit this slot.
:ref:`Heap subtypes <heap-types>` do not inherit this slot.

**Default:**

For dynamic subtypes, this field is always set to
For heap subtypes, this field is always set to
:c:func:`PyType_GenericAlloc`.

For static subtypes, this slot is inherited (see above).
Expand Down Expand Up @@ -2145,11 +2138,11 @@ and :c:data:`PyType_Type` effectively act as defaults.)
:c:func:`PyObject_Free`, then this slot is not inherited but instead defaults
to :c:func:`PyObject_GC_Del`.

Dynamic subtypes (created by a class statement) do not inherit this slot.
:ref:`Heap subtypes <heap-types>` do not inherit this slot.

**Default:**

For dynamic subtypes, this slot defaults to a deallocator suitable to match
For :ref:`heap subtypes <heap-types>`, this slot defaults to a deallocator suitable to match
:c:func:`PyType_GenericAlloc` and the value of the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag.

Expand Down Expand Up @@ -2289,7 +2282,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
The primary purpose of finalization is to perform any non-trivial cleanup
that must be performed before the object is destroyed, while the object and
any other objects it directly or indirectly references are still in a
consistent state. See :pep:`442`. The finalizer is allowed to execute
consistent state. The finalizer is allowed to execute
arbitrary Python code.

Before Python automatically finalizes an object, some of the object's direct
Expand All @@ -2301,28 +2294,28 @@ and :c:data:`PyType_Type` effectively act as defaults.)
finalizer must leave the object in a sane state (e.g., invariants are still
met).

.. warning::
.. note::

After Python automatically finalizes an object, Python might start
automatically clearing (:c:member:`~PyTypeObject.tp_clear`) the object
and its referents (direct and indirect). Cleared objects are not
guaranteed to be in a consistent state; a finalized object must be able
to tolerate cleared referents.

.. warning::
.. note::

An object is not guaranteed to be automatically finalized before its
destructor (:c:member:`~PyTypeObject.tp_dealloc`) is called. It is
recommended to call :c:func:`PyObject_CallFinalizerFromDealloc` at the
beginning of :c:member:`!tp_dealloc` to guarantee that the object is
always finalized before destruction.

.. warning::
.. note::

The :c:member:`~PyTypeObject.tp_finalize` function can be called from any
thread, although the :term:`GIL` will be held.

.. warning::
.. note::

The :c:member:`!tp_finalize` function can be called during shutdown,
after some global variables have been deleted. See the documentation of
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.