classification
Title: [C API] Add Py_NewRef() function to get a new strong reference to an object
Type: Stage: resolved
Components: C API Versions: Python 3.10
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: erlendaasland, hodgestar, vstinner
Priority: normal Keywords: patch

Created on 2020-11-04 16:20 by vstinner, last changed 2020-12-03 13:01 by vstinner. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 23152 merged vstinner, 2020-11-04 16:24
PR 23626 merged vstinner, 2020-12-03 11:43
Messages (4)
msg380337 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-11-04 16:20
In C, the following pattern (A) is very common:

    Py_INCREF(sysdict);
    interp->sysdict = sysdict;

* (1) Increment the reference counter
* (2) Store a reference to the object somewhere

Similar pattern (B) using return:

    Py_INCREF(temp);
    return temp;

The problem in these patterns is that the object has to be written twice. I propose to add a simple new Py_NewRef() function which returns a new strong reference. In short, it's just:

static inline PyObject* Py_NewRef(PyObject *obj)
{
    Py_INCREF(obj);
    return obj;
}

(The actual implementation is just a little bit more complex, to also export it as a regular function.)

Pattern (A) becomes:

    interp->sysdict = Py_NewRef(sysdict);

Pattern (B) becomes:

    
    return Py_NewRef(temp);

Py_NewRef() might help to prepare a C extension to be converted to HPy which uses a HPy_Dup() function. HPy_Dup() is different than "Py_INCREF(obj), obj" for subtle reasons. I let you dig into HPy documentation for the rationale:

https://hpy.readthedocs.io/en/latest/api.html#handles

Even if you ignore HPy, Py_NewRef() avoids to repeat the object variable, and so makes the code simpler. Simple example:

-#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#define Py_RETURN_NONE return Py_NewRef(Py_None)
msg380339 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-11-04 16:31
> The problem in these patterns is that the object has to be written twice.

I'm talking about the variable name which has to be repeated (written twice) in the source code.
msg380409 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-11-05 14:02
New changeset 53a03aafd5812018a3821a2e83063fd3d6cd2576 by Victor Stinner in branch 'master':
bpo-42262: Add Py_NewRef() and Py_XNewRef() (GH-23152)
https://github.com/python/cpython/commit/53a03aafd5812018a3821a2e83063fd3d6cd2576
msg382407 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-12-03 13:01
New changeset 8b6c4a921af6d5d0a9640211ac93d7886a55a8f3 by Victor Stinner in branch 'master':
bpo-42262: Py_NewRef() casts its argument to PyObject* (GH-23626)
https://github.com/python/cpython/commit/8b6c4a921af6d5d0a9640211ac93d7886a55a8f3
History
Date User Action Args
2020-12-03 13:01:17vstinnersetmessages: + msg382407
2020-12-03 11:43:10vstinnersetpull_requests: + pull_request22494
2020-11-05 14:11:51vstinnersetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2020-11-05 14:02:40vstinnersetmessages: + msg380409
2020-11-04 18:07:33erlendaaslandsetnosy: + erlendaasland
2020-11-04 16:32:56hodgestarsetnosy: + hodgestar
2020-11-04 16:31:42vstinnersetmessages: + msg380339
2020-11-04 16:24:25vstinnersetkeywords: + patch
stage: patch review
pull_requests: + pull_request22064
2020-11-04 16:20:34vstinnercreate