https://github.com/python/cpython/commit/06d76c4b94f87b0785a96dbfa0904afc0b459cb7
commit: 06d76c4b94f87b0785a96dbfa0904afc0b459cb7
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2024-07-17T01:57:37+08:00
summary:

[3.13] gh-121621: Move asyncio running loop to thread state (GH-121695) 
(GH-121864)

gh-121621: Move asyncio running loop to thread state (GH-121695)
(cherry picked from commit 69c68de43aef03dd52fabd21f99cb3b0f9329201)

Co-authored-by: Ken Jin <[email protected]>

files:
M Include/cpython/pystate.h
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Modules/_asynciomodule.c
M Python/pystate.c

diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index bb2af78a376d75..ce050424cccd49 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -68,6 +68,8 @@ struct _ts {
        pycore_ceval.h. */
     uintptr_t eval_breaker;
 
+    PyObject *asyncio_running_loop; // Strong reference
+
     struct {
         /* Has been initialized to a safe state.
 
diff --git a/Include/internal/pycore_global_objects_fini_generated.h 
b/Include/internal/pycore_global_objects_fini_generated.h
index 16cb4793ad1d08..006dd911b5a8ef 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -586,7 +586,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__anext__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__annotations__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__args__));
-    _PyStaticObject_CheckRefcnt((PyObject 
*)&_Py_ID(__asyncio_running_event_loop__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__await__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bases__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bool__));
diff --git a/Include/internal/pycore_global_strings.h 
b/Include/internal/pycore_global_strings.h
index 1e76853297150b..a5436b6d689612 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -75,7 +75,6 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(__anext__)
         STRUCT_FOR_ID(__annotations__)
         STRUCT_FOR_ID(__args__)
-        STRUCT_FOR_ID(__asyncio_running_event_loop__)
         STRUCT_FOR_ID(__await__)
         STRUCT_FOR_ID(__bases__)
         STRUCT_FOR_ID(__bool__)
diff --git a/Include/internal/pycore_runtime_init_generated.h 
b/Include/internal/pycore_runtime_init_generated.h
index f4d0ee4122ea2f..6e62ecd4b3a815 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -584,7 +584,6 @@ extern "C" {
     INIT_ID(__anext__), \
     INIT_ID(__annotations__), \
     INIT_ID(__args__), \
-    INIT_ID(__asyncio_running_event_loop__), \
     INIT_ID(__await__), \
     INIT_ID(__bases__), \
     INIT_ID(__bool__), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h 
b/Include/internal/pycore_unicodeobject_generated.h
index e1bc9cf1c7bd6e..5337390309548b 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -104,10 +104,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
     _PyUnicode_InternStatic(interp, &string);
     assert(_PyUnicode_CheckConsistency(string, 1));
     assert(PyUnicode_GET_LENGTH(string) != 1);
-    string = &_Py_ID(__asyncio_running_event_loop__);
-    _PyUnicode_InternStatic(interp, &string);
-    assert(_PyUnicode_CheckConsistency(string, 1));
-    assert(PyUnicode_GET_LENGTH(string) != 1);
     string = &_Py_ID(__await__);
     _PyUnicode_InternStatic(interp, &string);
     assert(_PyUnicode_CheckConsistency(string, 1));
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 92d0e6de0dfb93..ab72cc2fe55637 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -68,9 +68,6 @@ typedef struct {
     /* Imports from traceback. */
     PyObject *traceback_extract_stack;
 
-    PyObject *cached_running_loop; // Borrowed reference
-    volatile uint64_t cached_running_loop_tsid;
-
     /* Counter for autogenerated Task names */
     uint64_t task_name_counter;
 
@@ -262,101 +259,15 @@ get_future_loop(asyncio_state *state, PyObject *fut)
     return PyObject_GetAttr(fut, &_Py_ID(_loop));
 }
 
-
-static int
-get_running_loop(asyncio_state *state, PyObject **loop)
-{
-    PyObject *rl;
-
-    PyThreadState *ts = _PyThreadState_GET();
-    uint64_t ts_id = PyThreadState_GetID(ts);
-    if (state->cached_running_loop_tsid == ts_id &&
-        state->cached_running_loop != NULL)
-    {
-        // Fast path, check the cache.
-        rl = state->cached_running_loop;
-    }
-    else {
-        PyObject *ts_dict = _PyThreadState_GetDict(ts);  // borrowed
-        if (ts_dict == NULL) {
-            goto not_found;
-        }
-
-        rl = PyDict_GetItemWithError(
-            ts_dict, &_Py_ID(__asyncio_running_event_loop__));  // borrowed
-        if (rl == NULL) {
-            if (PyErr_Occurred()) {
-                goto error;
-            }
-            else {
-                goto not_found;
-            }
-        }
-
-        // TODO GH-121621: This should be moved to PyThreadState
-        // for easier and quicker access.
-        state->cached_running_loop = rl;
-        state->cached_running_loop_tsid = ts_id;
-    }
-
-
-    if (rl == Py_None) {
-        goto not_found;
-    }
-
-    *loop = Py_NewRef(rl);
-    return 0;
-
-not_found:
-    *loop = NULL;
-    return 0;
-
-error:
-    *loop = NULL;
-    return -1;
-}
-
-
-static int
-set_running_loop(asyncio_state *state, PyObject *loop)
-{
-    PyObject *ts_dict = NULL;
-
-    PyThreadState *tstate = _PyThreadState_GET();
-    if (tstate != NULL) {
-        ts_dict = _PyThreadState_GetDict(tstate);  // borrowed
-    }
-
-    if (ts_dict == NULL) {
-        PyErr_SetString(
-            PyExc_RuntimeError, "thread-local storage is not available");
-        return -1;
-    }
-    if (PyDict_SetItem(
-            ts_dict, &_Py_ID(__asyncio_running_event_loop__), loop) < 0)
-    {
-        return -1;
-    }
-
-
-    // TODO GH-121621: This should be moved to PyThreadState
-    // for easier and quicker access.
-    state->cached_running_loop = loop; // borrowed, kept alive by ts_dict
-    state->cached_running_loop_tsid = PyThreadState_GetID(tstate);
-
-    return 0;
-}
-
-
 static PyObject *
 get_event_loop(asyncio_state *state)
 {
     PyObject *loop;
     PyObject *policy;
 
-    if (get_running_loop(state, &loop)) {
-        return NULL;
-    }
+    PyThreadState *ts = _PyThreadState_GET();
+    loop = Py_XNewRef(ts->asyncio_running_loop);
+
     if (loop != NULL) {
         return loop;
     }
@@ -3278,11 +3189,8 @@ static PyObject *
 _asyncio__get_running_loop_impl(PyObject *module)
 /*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
 {
-    PyObject *loop;
-    asyncio_state *state = get_asyncio_state(module);
-    if (get_running_loop(state, &loop)) {
-        return NULL;
-    }
+    PyThreadState *ts = _PyThreadState_GET();
+    PyObject *loop = Py_XNewRef(ts->asyncio_running_loop);
     if (loop == NULL) {
         /* There's no currently running event loop */
         Py_RETURN_NONE;
@@ -3305,10 +3213,11 @@ static PyObject *
 _asyncio__set_running_loop(PyObject *module, PyObject *loop)
 /*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
 {
-    asyncio_state *state = get_asyncio_state(module);
-    if (set_running_loop(state, loop)) {
-        return NULL;
+    PyThreadState *ts = _PyThreadState_GET();
+    if (loop == Py_None) {
+        loop = NULL;
     }
+    Py_XSETREF(ts->asyncio_running_loop, Py_XNewRef(loop));
     Py_RETURN_NONE;
 }
 
@@ -3346,14 +3255,13 @@ _asyncio_get_running_loop_impl(PyObject *module)
 /*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
 {
     PyObject *loop;
-    asyncio_state *state = get_asyncio_state(module);
-    if (get_running_loop(state, &loop)) {
-        return NULL;
-    }
+    PyThreadState *ts = _PyThreadState_GET();
+    loop = Py_XNewRef(ts->asyncio_running_loop);
     if (loop == NULL) {
         /* There's no currently running event loop */
         PyErr_SetString(
             PyExc_RuntimeError, "no running event loop");
+        return NULL;
     }
     return loop;
 }
diff --git a/Python/pystate.c b/Python/pystate.c
index 602b13e18c71ae..f77a2cc54e867a 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -1499,6 +1499,8 @@ init_threadstate(_PyThreadStateImpl *_tstate,
     tstate->previous_executor = NULL;
     tstate->dict_global_version = 0;
 
+    tstate->asyncio_running_loop = NULL;
+
     tstate->delete_later = NULL;
 
     llist_init(&_tstate->mem_free_queue);
@@ -1700,6 +1702,8 @@ PyThreadState_Clear(PyThreadState *tstate)
 
     /* Don't clear tstate->pyframe: it is a borrowed reference */
 
+    Py_CLEAR(tstate->asyncio_running_loop);
+
     Py_CLEAR(tstate->dict);
     Py_CLEAR(tstate->async_exc);
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to