Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from1 commit
bc32398
361eaca
b27bcca
b42b58d
7e571ae
97dc30c
85e535a
ef979e6
f3863c4
6a114f9
182c977
7cd0cb5
e34e224
16a29ab
018a3c4
442b7f2
5ed484a
b7774ae
bb1a94f
fd38fd4
3573c79
2633594
c57574a
878fd27
1b96fad
e8c6852
3408919
b6023a3
da3593c
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
* Add "cyclic isolate" to the glossary. * Add a new "Object Life Cycle" page. * Illustrate the order of life cycle functions. * Document `PyObject_CallFinalizer` and `PyObject_CallFinalizerFromDealloc`. * `PyObject_Init` does not call `tp_init`. * `PyObject_New`: * also initializes the memory * does not call `tp_alloc`, `tp_new`, or `tp_init` * should not be used for GC-enabled objects * memory must be freed by `PyObject_Free` * `PyObject_GC_New` memory must be freed by `PyObject_GC_Del`. * Warn that garbage collector functions can be called from any thread. * `tp_finalize` and `tp_clear`: * Only called when there's a cyclic isolate. * Only one object in the cyclic isolate is finalized/cleared at a time. * Clearly warn that they might not be called. * They can optionally be manually called from `tp_dealloc` (via `PyObject_CallFinalizerFromDealloc` in the case of `tp_finalize`). * `tp_finalize`: * Reference `object.__del__`. * The finalizer can resurrect the object. * Suggest `PyErr_GetRaisedException` and `PyErr_SetRaisedException` instead of the deprecated `PyErr_Fetch` and `PyErr_Restore` functions. * Add links to `PyErr_GetRaisedException` and `PyErr_SetRaisedException`. * Suggest using `PyErr_WriteUnraisable` if an exception is raised during finalization. * Rename the example function from `local_finalize` to `foo_finalize` for consistency with the `tp_dealloc` documentation and as a hint that the name isn't special. * Minor wording and sylistic tweaks. * Warn that `tp_finalize` can be called during shutdown.
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -18,7 +18,8 @@ Allocating Objects on the Heap | ||
reference. Returns the initialized object. If *type* indicates that the | ||
object participates in the cyclic garbage detector, it is added to the | ||
detector's set of observed objects. Other fields of the object are not | ||
initialized. Specifically, this function does **not** call the object's | ||
:meth:`~object.__init__` method (:c:member:`~PyTypeObject.tp_init` slot). | ||
.. c:function:: PyVarObject* PyObject_InitVar(PyVarObject *op, PyTypeObject *type, Py_ssize_t size) | ||
@@ -29,27 +30,44 @@ Allocating Objects on the Heap | ||
..c:macro:: PyObject_New(TYPE, typeobj) | ||
Calls:c:func:`PyObject_Malloc` to allocate memory for a new Python object | ||
using the C structure type *TYPE* and the Python type object *typeobj* | ||
(``PyTypeObject*``), then initializes the memory like | ||
:c:func:`PyObject_Init`. The caller will own the only reference to the | ||
object (i.e. its reference count will be one). The size of the memory | ||
allocation is determined from the :c:member:`~PyTypeObject.tp_basicsize` | ||
field of the type object. | ||
rhansen marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page.
rhansen marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
This does not call :c:member:`~PyTypeObject.tp_alloc`, | ||
:c:member:`~PyTypeObject.tp_new` (:meth:`~object.__new__`), or | ||
:c:member:`~PyTypeObject.tp_init` (:meth:`~object.__init__`). | ||
This should not 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`. | ||
..c:macro:: PyObject_NewVar(TYPE, typeobj, size) | ||
Like:c:macro:`PyObject_New` except: | ||
* It allocates enough memory for the *TYPE* structure plus *size* | ||
(``Py_ssize_t``) fields of the size given by the | ||
:c:member:`~PyTypeObject.tp_itemsize` field of *typeobj*. | ||
* The memory is initialized like :c:func:`PyObject_InitVar`. | ||
This is useful for implementing objects like tuples, which are able to | ||
determine their size at construction time. Embedding the array of fields | ||
into the same allocation decreases the number of allocations, improving the | ||
memory management efficiency. | ||
This should not be used for objects with :c:macro:`Py_TPFLAGS_HAVE_GC` set | ||
in :c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_NewVar` | ||
instead. | ||
Memory allocated by this function must be freed with:c:func:`PyObject_Free`. | ||
..c:function::voidPyObject_Del(void *op) | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -57,11 +57,17 @@ rules: | ||
Analogous to:c:macro:`PyObject_New` but for container objects with the | ||
:c:macro:`Py_TPFLAGS_HAVE_GC` flag set. | ||
Memory allocated by this function must be freed with | ||
ZeroIntensity marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
:c:func:`PyObject_GC_Del`. | ||
rhansen marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
..c:macro:: PyObject_GC_NewVar(TYPE, typeobj, size) | ||
Analogous to:c:macro:`PyObject_NewVar` but for container objects with the | ||
:c:macro:`Py_TPFLAGS_HAVE_GC` flag set. | ||
Memory allocated by this function must be freed with | ||
ZeroIntensity marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
:c:func:`PyObject_GC_Del`. | ||
..c:function:: PyObject*PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size) | ||
Analogous to:c:macro:`PyObject_GC_New` but allocates *extra_size* | ||
@@ -73,6 +79,9 @@ rules: | ||
The extra data will be deallocated with the object, but otherwise it is | ||
not managed by Python. | ||
Memory allocated by this function must be freed with | ||
:c:func:`PyObject_GC_Del`. | ||
.. warning:: | ||
The function is marked as unstable because thefinal mechanism | ||
for reserving extra data after an instance is not yet decided. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
digraph G { | ||
graph [ | ||
fontname="svg" | ||
fontsize=10.0 | ||
layout="dot" | ||
ranksep=0.25 | ||
] | ||
node [ | ||
fontname="Courier" | ||
fontsize=10.0 | ||
] | ||
edge [ | ||
fontname="Times-Italic" | ||
fontsize=10.0 | ||
] | ||
"start" [fontname="Times-Italic" shape=plain label=< start > style=invis] | ||
"tp_alloc" [href="typeobj.html#c.PyTypeObject.tp_alloc" target="_top"] | ||
"tp_new" [href="typeobj.html#c.PyTypeObject.tp_new" target="_top"] | ||
"tp_init" [href="typeobj.html#c.PyTypeObject.tp_init" target="_top"] | ||
{ | ||
rank="same" | ||
"alive" [ | ||
fontname="Times-Italic" | ||
label=<alive, ref count > 0> | ||
shape=box | ||
] | ||
"tp_traverse" [ | ||
href="typeobj.html#c.PyTypeObject.tp_traverse" | ||
shape=octagon | ||
target="_top" | ||
] | ||
} | ||
"tp_finalize" [ | ||
href="typeobj.html#c.PyTypeObject.tp_finalize" | ||
shape=octagon | ||
target="_top" | ||
] | ||
"tp_clear" [ | ||
href="typeobj.html#c.PyTypeObject.tp_clear" | ||
shape=octagon | ||
target="_top" | ||
] | ||
"ref0" [ | ||
fontname="Times-Italic" | ||
label=<ref count == 0> | ||
ordering="in" | ||
shape=box | ||
] | ||
"tp_dealloc" [href="typeobj.html#c.PyTypeObject.tp_dealloc" target="_top"] | ||
"tp_free" [href="typeobj.html#c.PyTypeObject.tp_free" target="_top"] | ||
"start" -> "tp_alloc" | ||
"tp_alloc" -> "tp_new" | ||
"tp_new" -> "tp_init" | ||
"tp_init" -> "alive" | ||
"tp_traverse" -> "alive" | ||
"alive" -> "tp_traverse" | ||
"alive" -> "tp_clear" [label=< cyclic <br/>isolate >] | ||
"alive" -> "tp_finalize" [ | ||
dir="back" | ||
label=< resurrected > | ||
] | ||
"alive" -> "tp_finalize" [label=< cyclic <br/>isolate >] | ||
"tp_finalize" -> "tp_clear" | ||
"tp_finalize" -> "ref0" | ||
"tp_clear" -> "ref0" | ||
"tp_clear" -> "tp_dealloc" [ | ||
dir="back" | ||
label=< optional<br/>direct call > | ||
] | ||
"alive" -> "ref0" | ||
"ref0" -> "tp_dealloc" | ||
"tp_finalize" -> "tp_dealloc" [ | ||
dir="back" | ||
href="lifecycle.html#c.PyObject_CallFinalizerFromDealloc" | ||
label=< | ||
<table border="0" cellborder="0" cellpadding="0" cellspacing="0"> | ||
<tr> | ||
<td rowspan="4"> </td> | ||
<td align="left">optional call to</td> | ||
<td rowspan="4"> </td> | ||
</tr> | ||
<tr> | ||
<td align="left"><font face="Courier">PyObject_Call</font></td> | ||
</tr> | ||
<tr> | ||
<td align="left"><font face="Courier">FinalizerFrom</font></td> | ||
</tr> | ||
<tr><td align="left"><font face="Courier">Dealloc</font></td></tr> | ||
</table> | ||
> | ||
target="_top" | ||
] | ||
"tp_dealloc" -> "tp_free" [label=< directly calls >] | ||
} |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.