Skip to content

Commit a5fbef8

Browse files
committed
feat: to get the running event-loop in Python 3.13 is as simple as thread_state->asyncio_running_loop
1 parent b2fb169 commit a5fbef8

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

src/PyEventLoop.cc

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,26 @@ PyEventLoop PyEventLoop::_getLoopOnThread(PyThreadState *tstate) {
147147
// However, simply replacing it with `PyThreadState_GetDict()` does not work,
148148
// since the public `PyThreadState_GetDict()` API can only get from the current thread.
149149
// We need to somehow get the thread dictionary on the main thread instead of the current thread.
150-
if (!tstate->dict) {
151-
// Modified from https://github.com/python/cpython/blob/v3.13.0rc1/Python/pystate.c#L1934-L1951
152-
tstate->dict = PyDict_New();
153-
if (tstate->dict == NULL) { // when it's still null, no per-thread state is available, and an exception should not be raised
154-
PyObject *old_exc = tstate->current_exception;
155-
tstate->current_exception = NULL; // _PyErr_Clear(tstate)
156-
Py_XDECREF(old_exc);
150+
//
151+
// UPDATE: We don't need the thread dictionary anymore.
152+
// To get the thread's running event-loop in Python 3.13 is as simple as `thread_state->asyncio_running_loop`
153+
{
154+
// Every `PyThreadState` is actually allocated with extra fields as a `_PyThreadStateImpl` struct
155+
// See https://github.com/python/cpython/blob/v3.13.0rc1/Include/internal/pycore_tstate.h#L17-L24
156+
using PyThreadStateHolder = struct { // _PyThreadStateImpl
157+
PyThreadState base;
158+
PyObject *asyncio_running_loop; // we only need the first field of `_PyThreadStateImpl`
159+
};
160+
161+
// Modified from https://github.com/python/cpython/blob/v3.13.0rc1/Modules/_asynciomodule.c#L3205-L3210
162+
PyObject *loop = ((PyThreadStateHolder *)tstate)->asyncio_running_loop;
163+
if (loop == NULL) {
157164
return _loopNotFound();
158165
}
166+
167+
Py_INCREF(loop);
168+
return PyEventLoop(loop);
159169
}
160-
ts_dict = tstate->dict;
161170
#elif PY_VERSION_HEX >= 0x03090000 // Python version is greater than 3.9
162171
ts_dict = _PyThreadState_GetDict(tstate); // borrowed reference
163172
#else // Python 3.8

0 commit comments

Comments
 (0)