@@ -147,17 +147,26 @@ PyEventLoop PyEventLoop::_getLoopOnThread(PyThreadState *tstate) {
147
147
// However, simply replacing it with `PyThreadState_GetDict()` does not work,
148
148
// since the public `PyThreadState_GetDict()` API can only get from the current thread.
149
149
// 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 ) {
157
164
return _loopNotFound ();
158
165
}
166
+
167
+ Py_INCREF (loop);
168
+ return PyEventLoop (loop);
159
169
}
160
- ts_dict = tstate->dict ;
161
170
#elif PY_VERSION_HEX >= 0x03090000 // Python version is greater than 3.9
162
171
ts_dict = _PyThreadState_GetDict (tstate); // borrowed reference
163
172
#else // Python 3.8
0 commit comments