MCPcopy Create free account
hub / github.com/Distributive-Network/PythonMonkey / _getLoopOnThread

Method _getLoopOnThread

src/PyEventLoop.cc:141–211  ·  view source on GitHub ↗

static */

Source from the content-addressed store, hash-verified

139
140/* static */
141PyEventLoop PyEventLoop::_getLoopOnThread(PyThreadState *tstate) {
142 // Modified from Python 3.9 `get_running_loop` https://github.com/python/cpython/blob/7cb3a44/Modules/_asynciomodule.c#L241-L278
143
144 PyObject *ts_dict;
145 #if PY_VERSION_HEX >= 0x030d0000 // Python version is greater than 3.13
146 // The private `_PyThreadState_GetDict(tstate)` API gets removed in Python 3.13.
147 // However, simply replacing it with `PyThreadState_GetDict()` does not work,
148 // since the public `PyThreadState_GetDict()` API can only get from the current thread.
149 // We need to somehow get the thread dictionary on the main thread instead of the current thread.
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 #if PY_VERSION_HEX >= 0x030e0000 // Python version is greater than 3.14
159 // the struct is changed with more additional fields, see https://github.com/python/cpython/blob/v3.14.0rc3/Include/internal/pycore_tstate.h#L24-L40
160 Py_ssize_t refcount;
161 uintptr_t c_stack_top;
162 uintptr_t c_stack_soft_limit;
163 uintptr_t c_stack_hard_limit;
164 #endif
165 PyObject *asyncio_running_loop; // we only need the first few fields of `_PyThreadStateImpl`
166 };
167
168 // Modified from https://github.com/python/cpython/blob/v3.13.0rc1/Modules/_asynciomodule.c#L3205-L3210
169 PyObject *loop = ((PyThreadStateHolder *)tstate)->asyncio_running_loop;
170 if (loop == NULL) {
171 return _loopNotFound();
172 }
173
174 Py_INCREF(loop);
175 return PyEventLoop(loop);
176 }
177 #elif PY_VERSION_HEX >= 0x03090000 // Python version is greater than 3.9
178 ts_dict = _PyThreadState_GetDict(tstate); // borrowed reference
179 #else // Python 3.8
180 ts_dict = tstate->dict; // see https://github.com/python/cpython/blob/v3.8.17/Modules/_asynciomodule.c#L244-L245
181 #endif
182 if (ts_dict == NULL) {
183 return _loopNotFound();
184 }
185
186 // TODO: Python `get_running_loop` caches the PyRunningLoopHolder, should we do it as well for the main thread?
187 // see https://github.com/python/cpython/blob/7cb3a44/Modules/_asynciomodule.c#L234-L239
188 PyObject *rl = PyDict_GetItemString(ts_dict, "__asyncio_running_event_loop__"); // borrowed reference
189 if (rl == NULL) {
190 return _loopNotFound();
191 }
192
193#if PY_VERSION_HEX < 0x030c0000 // Python version is less than 3.12
194 using PyRunningLoopHolder = struct {
195 PyObject_HEAD
196 PyObject *rl_loop;
197 };
198

Callers

nothing calls this directly

Calls 1

PyEventLoopClass · 0.85

Tested by

no test coverage detected