From 23c5f93b83f78f295313e137011edb18b24c37c2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Nov 2020 13:40:47 +0100 Subject: bpo-42294: Add borrowed/strong reference to doc glossary (GH-23206) Add "borrowed reference" and "strong reference" to the documentation glossary. Enhance also Py_INCREF() and Py_NewRef() documentation. --- Doc/c-api/arg.rst | 3 ++- Doc/c-api/init.rst | 2 +- Doc/c-api/intro.rst | 2 +- Doc/c-api/refcounting.rst | 35 ++++++++++++++++++++++++++--------- Doc/c-api/reflection.rst | 4 ++-- Doc/c-api/structures.rst | 2 +- Doc/c-api/typeobj.rst | 5 +++-- Doc/c-api/weakref.rst | 6 +++--- Doc/data/refcounts.dat | 6 ++++++ Doc/glossary.rst | 24 ++++++++++++++++++++++++ Include/object.h | 5 +++-- 11 files changed, 72 insertions(+), 22 deletions(-) diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index bdaae44..a91b3c7 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -482,7 +482,8 @@ API Functions *min* and no more than *max*; *min* and *max* may be equal. Additional arguments must be passed to the function, each of which should be a pointer to a :c:type:`PyObject*` variable; these will be filled in with the values from - *args*; they will contain borrowed references. The variables which correspond + *args*; they will contain :term:`borrowed references `. + The variables which correspond to optional parameters not given by *args* will not be filled in; these should be initialized by the caller. This function returns true on success and false if *args* is not a tuple or contains the wrong number of elements; an exception diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 3ce6892..3d18bb3 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1077,7 +1077,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`. Get the current frame of the Python thread state *tstate*. - Return a strong reference. Return ``NULL`` if no frame is currently + Return a :term:`strong reference`. Return ``NULL`` if no frame is currently executing. See also :c:func:`PyEval_GetFrame`. diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 7ca8693..bae5ce1 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -326,7 +326,7 @@ when it's no longer needed---or passing on this responsibility (usually to its caller). When a function passes ownership of a reference on to its caller, the caller is said to receive a *new* reference. When no ownership is transferred, the caller is said to *borrow* the reference. Nothing needs to be done for a -borrowed reference. +:term:`borrowed reference`. Conversely, when a calling function passes in a reference to an object, there are two possibilities: the function *steals* a reference to the object, or it diff --git a/Doc/c-api/refcounting.rst b/Doc/c-api/refcounting.rst index b15c0e6..391907c 100644 --- a/Doc/c-api/refcounting.rst +++ b/Doc/c-api/refcounting.rst @@ -13,10 +13,14 @@ objects. .. c:function:: void Py_INCREF(PyObject *o) - Increment the reference count for object *o*. The object must not be ``NULL``; if - you aren't sure that it isn't ``NULL``, use :c:func:`Py_XINCREF`. + Increment the reference count for object *o*. - See also :c:func:`Py_NewRef`. + This function is usually used to convert a :term:`borrowed reference` to a + :term:`strong reference` in-place. The :c:func:`Py_NewRef` function can be + used to create a new :term:`strong reference`. + + The object must not be ``NULL``; if you aren't sure that it isn't + ``NULL``, use :c:func:`Py_XINCREF`. .. c:function:: void Py_XINCREF(PyObject *o) @@ -29,9 +33,14 @@ objects. .. c:function:: PyObject* Py_NewRef(PyObject *o) - Increment the reference count of the object *o* and return the object *o*. + Create a new :term:`strong reference` to an object: increment the reference + count of the object *o* and return the object *o*. + + When the :term:`strong reference` is no longer needed, :c:func:`Py_DECREF` + should be called on it to decrement the object reference count. - The object *o* must not be ``NULL``. + The object *o* must not be ``NULL``; use :c:func:`Py_XNewRef` if *o* can be + ``NULL``. For example:: @@ -42,6 +51,8 @@ objects. self->attr = Py_NewRef(obj); + See also :c:func:`Py_INCREF`. + .. versionadded:: 3.10 @@ -56,10 +67,16 @@ objects. .. c:function:: void Py_DECREF(PyObject *o) - Decrement the reference count for object *o*. The object must not be ``NULL``; if - you aren't sure that it isn't ``NULL``, use :c:func:`Py_XDECREF`. If the reference - count reaches zero, the object's type's deallocation function (which must not be - ``NULL``) is invoked. + Decrement the reference count for object *o*. + + If the reference count reaches zero, the object's type's deallocation + function (which must not be ``NULL``) is invoked. + + This function is usually used to delete a :term:`strong reference` before + exiting its scope. + + The object must not be ``NULL``; if you aren't sure that it isn't ``NULL``, + use :c:func:`Py_XDECREF`. .. warning:: diff --git a/Doc/c-api/reflection.rst b/Doc/c-api/reflection.rst index 9207d86..64ce4d1 100644 --- a/Doc/c-api/reflection.rst +++ b/Doc/c-api/reflection.rst @@ -35,7 +35,7 @@ Reflection Get the *frame* next outer frame. - Return a strong reference, or ``NULL`` if *frame* has no outer frame. + Return a :term:`strong reference`, or ``NULL`` if *frame* has no outer frame. *frame* must not be ``NULL``. @@ -46,7 +46,7 @@ Reflection Get the *frame* code. - Return a strong reference. + Return a :term:`strong reference`. *frame* must not be ``NULL``. The result (frame code) cannot be ``NULL``. diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index a9e1c6f..03fe479 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -66,7 +66,7 @@ the definition of all other Python objects. Get the type of the Python object *o*. - Return a borrowed reference. + Return a :term:`borrowed reference`. .. versionchanged:: 3.10 :c:func:`Py_TYPE()` is changed to the inline static function. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index ddcb8ae..32bbc7b 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1213,8 +1213,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) :func:`~gc.get_referents` function will include it. .. warning:: - When implementing :c:member:`~PyTypeObject.tp_traverse`, only the members - that the instance *owns* (by having strong references to them) must be + When implementing :c:member:`~PyTypeObject.tp_traverse`, only the + members that the instance *owns* (by having :term:`strong references + ` to them) must be visited. For instance, if an object supports weak references via the :c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting the linked list (what *tp_weaklist* points to) must **not** be diff --git a/Doc/c-api/weakref.rst b/Doc/c-api/weakref.rst index e3a9bda..fb6628a 100644 --- a/Doc/c-api/weakref.rst +++ b/Doc/c-api/weakref.rst @@ -57,10 +57,10 @@ as much as it can. .. note:: - This function returns a **borrowed reference** to the referenced object. + This function returns a :term:`borrowed reference` to the referenced object. This means that you should always call :c:func:`Py_INCREF` on the object - except if you know that it cannot be destroyed while you are still - using it. + except it cannot be destroyed before the last usage of the borrowed + reference. .. c:function:: PyObject* PyWeakref_GET_OBJECT(PyObject *ref) diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index d01e99c..8a6ee71 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -3007,6 +3007,9 @@ Py_GetVersion:const char*::: Py_INCREF:void::: Py_INCREF:PyObject*:o:+1: +Py_NewRef:void::: +Py_NewRef:PyObject*:o:+1: + Py_Initialize:void::: Py_IsInitialized:int::: @@ -3028,6 +3031,9 @@ Py_XDECREF:PyObject*:o:-1:if o is not NULL Py_XINCREF:void::: Py_XINCREF:PyObject*:o:+1:if o is not NULL +Py_XNewRef:void::: +Py_XNewRef:PyObject*:o:+1:if o is not NULL + _PyImport_Fini:void::: _PyObject_New:PyObject*::+1: diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 506973e..b410585 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -158,6 +158,18 @@ Glossary See also :term:`text file` for a file object able to read and write :class:`str` objects. + borrowed reference + In the Python's C API, a borrowed reference is a reference to an object. + It does not modify the object reference count. It becomes a dangling + pointer if the object is destroyed. For example, a garbage collection can + remove the last :term:`strong reference` to the object and so destroy it. + + Calling :c:func:`Py_INCREF` on the :term:`borrowed reference` is + recommended to convert it to a :term:`strong reference` in-place, except + if the object cannot be destroyed before the last usage of the borrowed + reference. The :c:func:`Py_NewRef` function can be used to create a new + :term:`strong reference`. + bytes-like object An object that supports the :ref:`bufferobjects` and can export a C-:term:`contiguous` buffer. This includes all :class:`bytes`, @@ -1100,6 +1112,18 @@ Glossary an :term:`expression` or one of several constructs with a keyword, such as :keyword:`if`, :keyword:`while` or :keyword:`for`. + strong reference + In the Python's C API, a strong reference is a reference to an object + which increments object reference count when it is created and + decrements the object reference count when it is deleted. + + The :c:func:`Py_NewRef` function can be used to create a strong reference + to an object. Usually, the :c:func:`Py_DECREF` function must be called on + the strong reference before exiting the scope of the strong reference, to + avoid leaking one reference. + + See also :term:`borrowed reference`. + text encoding A codec which encodes Unicode strings to bytes. diff --git a/Include/object.h b/Include/object.h index 835d9de..eab3228 100644 --- a/Include/object.h +++ b/Include/object.h @@ -526,10 +526,11 @@ they can have object code that is not dependent on Python compilation flags. PyAPI_FUNC(void) Py_IncRef(PyObject *); PyAPI_FUNC(void) Py_DecRef(PyObject *); -// Increment the reference count of the object and return the object. +// Create a new strong reference to an object: +// increment the reference count of the object and return the object. PyAPI_FUNC(PyObject*) Py_NewRef(PyObject *obj); -// Similar to Py_NewRef() but the object can be NULL. +// Similar to Py_NewRef(), but the object can be NULL. PyAPI_FUNC(PyObject*) Py_XNewRef(PyObject *obj); static inline PyObject* _Py_NewRef(PyObject *obj) -- cgit v0.12