mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
[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 69c68de43a
)
Co-authored-by: Ken Jin <kenjin@python.org>
This commit is contained in:
parent
54db42fe2c
commit
06d76c4b94
7 changed files with 18 additions and 111 deletions
|
@ -68,6 +68,8 @@ struct _ts {
|
||||||
pycore_ceval.h. */
|
pycore_ceval.h. */
|
||||||
uintptr_t eval_breaker;
|
uintptr_t eval_breaker;
|
||||||
|
|
||||||
|
PyObject *asyncio_running_loop; // Strong reference
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* Has been initialized to a safe state.
|
/* Has been initialized to a safe state.
|
||||||
|
|
||||||
|
|
|
@ -586,7 +586,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__anext__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__anext__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__annotations__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__annotations__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__args__));
|
_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(__await__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bases__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bases__));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bool__));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bool__));
|
||||||
|
|
|
@ -75,7 +75,6 @@ struct _Py_global_strings {
|
||||||
STRUCT_FOR_ID(__anext__)
|
STRUCT_FOR_ID(__anext__)
|
||||||
STRUCT_FOR_ID(__annotations__)
|
STRUCT_FOR_ID(__annotations__)
|
||||||
STRUCT_FOR_ID(__args__)
|
STRUCT_FOR_ID(__args__)
|
||||||
STRUCT_FOR_ID(__asyncio_running_event_loop__)
|
|
||||||
STRUCT_FOR_ID(__await__)
|
STRUCT_FOR_ID(__await__)
|
||||||
STRUCT_FOR_ID(__bases__)
|
STRUCT_FOR_ID(__bases__)
|
||||||
STRUCT_FOR_ID(__bool__)
|
STRUCT_FOR_ID(__bool__)
|
||||||
|
|
1
Include/internal/pycore_runtime_init_generated.h
generated
1
Include/internal/pycore_runtime_init_generated.h
generated
|
@ -584,7 +584,6 @@ extern "C" {
|
||||||
INIT_ID(__anext__), \
|
INIT_ID(__anext__), \
|
||||||
INIT_ID(__annotations__), \
|
INIT_ID(__annotations__), \
|
||||||
INIT_ID(__args__), \
|
INIT_ID(__args__), \
|
||||||
INIT_ID(__asyncio_running_event_loop__), \
|
|
||||||
INIT_ID(__await__), \
|
INIT_ID(__await__), \
|
||||||
INIT_ID(__bases__), \
|
INIT_ID(__bases__), \
|
||||||
INIT_ID(__bool__), \
|
INIT_ID(__bool__), \
|
||||||
|
|
|
@ -104,10 +104,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
|
||||||
_PyUnicode_InternStatic(interp, &string);
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
assert(PyUnicode_GET_LENGTH(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__);
|
string = &_Py_ID(__await__);
|
||||||
_PyUnicode_InternStatic(interp, &string);
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
|
|
|
@ -68,9 +68,6 @@ typedef struct {
|
||||||
/* Imports from traceback. */
|
/* Imports from traceback. */
|
||||||
PyObject *traceback_extract_stack;
|
PyObject *traceback_extract_stack;
|
||||||
|
|
||||||
PyObject *cached_running_loop; // Borrowed reference
|
|
||||||
volatile uint64_t cached_running_loop_tsid;
|
|
||||||
|
|
||||||
/* Counter for autogenerated Task names */
|
/* Counter for autogenerated Task names */
|
||||||
uint64_t task_name_counter;
|
uint64_t task_name_counter;
|
||||||
|
|
||||||
|
@ -262,101 +259,15 @@ get_future_loop(asyncio_state *state, PyObject *fut)
|
||||||
return PyObject_GetAttr(fut, &_Py_ID(_loop));
|
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 *
|
static PyObject *
|
||||||
get_event_loop(asyncio_state *state)
|
get_event_loop(asyncio_state *state)
|
||||||
{
|
{
|
||||||
PyObject *loop;
|
PyObject *loop;
|
||||||
PyObject *policy;
|
PyObject *policy;
|
||||||
|
|
||||||
if (get_running_loop(state, &loop)) {
|
PyThreadState *ts = _PyThreadState_GET();
|
||||||
return NULL;
|
loop = Py_XNewRef(ts->asyncio_running_loop);
|
||||||
}
|
|
||||||
if (loop != NULL) {
|
if (loop != NULL) {
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
|
@ -3278,11 +3189,8 @@ static PyObject *
|
||||||
_asyncio__get_running_loop_impl(PyObject *module)
|
_asyncio__get_running_loop_impl(PyObject *module)
|
||||||
/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
|
/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
|
||||||
{
|
{
|
||||||
PyObject *loop;
|
PyThreadState *ts = _PyThreadState_GET();
|
||||||
asyncio_state *state = get_asyncio_state(module);
|
PyObject *loop = Py_XNewRef(ts->asyncio_running_loop);
|
||||||
if (get_running_loop(state, &loop)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (loop == NULL) {
|
if (loop == NULL) {
|
||||||
/* There's no currently running event loop */
|
/* There's no currently running event loop */
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
@ -3305,10 +3213,11 @@ static PyObject *
|
||||||
_asyncio__set_running_loop(PyObject *module, PyObject *loop)
|
_asyncio__set_running_loop(PyObject *module, PyObject *loop)
|
||||||
/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
|
/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
|
||||||
{
|
{
|
||||||
asyncio_state *state = get_asyncio_state(module);
|
PyThreadState *ts = _PyThreadState_GET();
|
||||||
if (set_running_loop(state, loop)) {
|
if (loop == Py_None) {
|
||||||
return NULL;
|
loop = NULL;
|
||||||
}
|
}
|
||||||
|
Py_XSETREF(ts->asyncio_running_loop, Py_XNewRef(loop));
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3346,14 +3255,13 @@ _asyncio_get_running_loop_impl(PyObject *module)
|
||||||
/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
|
/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
|
||||||
{
|
{
|
||||||
PyObject *loop;
|
PyObject *loop;
|
||||||
asyncio_state *state = get_asyncio_state(module);
|
PyThreadState *ts = _PyThreadState_GET();
|
||||||
if (get_running_loop(state, &loop)) {
|
loop = Py_XNewRef(ts->asyncio_running_loop);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (loop == NULL) {
|
if (loop == NULL) {
|
||||||
/* There's no currently running event loop */
|
/* There's no currently running event loop */
|
||||||
PyErr_SetString(
|
PyErr_SetString(
|
||||||
PyExc_RuntimeError, "no running event loop");
|
PyExc_RuntimeError, "no running event loop");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1499,6 +1499,8 @@ init_threadstate(_PyThreadStateImpl *_tstate,
|
||||||
tstate->previous_executor = NULL;
|
tstate->previous_executor = NULL;
|
||||||
tstate->dict_global_version = 0;
|
tstate->dict_global_version = 0;
|
||||||
|
|
||||||
|
tstate->asyncio_running_loop = NULL;
|
||||||
|
|
||||||
tstate->delete_later = NULL;
|
tstate->delete_later = NULL;
|
||||||
|
|
||||||
llist_init(&_tstate->mem_free_queue);
|
llist_init(&_tstate->mem_free_queue);
|
||||||
|
@ -1700,6 +1702,8 @@ PyThreadState_Clear(PyThreadState *tstate)
|
||||||
|
|
||||||
/* Don't clear tstate->pyframe: it is a borrowed reference */
|
/* Don't clear tstate->pyframe: it is a borrowed reference */
|
||||||
|
|
||||||
|
Py_CLEAR(tstate->asyncio_running_loop);
|
||||||
|
|
||||||
Py_CLEAR(tstate->dict);
|
Py_CLEAR(tstate->dict);
|
||||||
Py_CLEAR(tstate->async_exc);
|
Py_CLEAR(tstate->async_exc);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue