Skip to content

Commit 24e9bd4

Browse files
committed
Simplify asyncio loop fast path guard
1 parent 02cd192 commit 24e9bd4

1 file changed

Lines changed: 30 additions & 22 deletions

File tree

Modules/_asynciomodule.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -366,28 +366,40 @@ get_event_loop(asyncio_state *state)
366366
}
367367

368368

369+
static int
370+
is_asyncio_base_event_loop_type(PyTypeObject *loop_type)
371+
{
372+
if (strcmp(loop_type->tp_name, "BaseEventLoop") != 0) {
373+
return 0;
374+
}
375+
376+
PyObject *module_name =
377+
PyDict_GetItemWithError(loop_type->tp_dict, &_Py_ID(__module__));
378+
if (module_name == NULL) {
379+
if (PyErr_Occurred()) {
380+
return -1;
381+
}
382+
return 0;
383+
}
384+
385+
return (
386+
PyUnicode_Check(module_name) &&
387+
PyUnicode_CompareWithASCIIString(module_name, "asyncio.base_events") == 0
388+
);
389+
}
390+
369391
static int
370392
is_asyncio_base_event_loop_subclass(PyTypeObject *loop_type)
371393
{
372394
// The _asyncio module is imported from asyncio.events while
373395
// asyncio.base_events is still initializing, so we can't cache the
374396
// BaseEventLoop type during module init without creating an import cycle.
375397
for (PyTypeObject *base = loop_type; base != NULL; base = base->tp_base) {
376-
if (strcmp(base->tp_name, "BaseEventLoop") != 0) {
377-
continue;
378-
}
379-
380-
PyObject *module_name =
381-
PyDict_GetItemWithError(base->tp_dict, &_Py_ID(__module__));
382-
if (module_name == NULL) {
383-
if (PyErr_Occurred()) {
384-
return -1;
385-
}
386-
continue;
398+
int is_base_event_loop = is_asyncio_base_event_loop_type(base);
399+
if (is_base_event_loop < 0) {
400+
return -1;
387401
}
388-
389-
if (PyUnicode_Check(module_name) &&
390-
PyUnicode_CompareWithASCIIString(module_name, "asyncio.base_events") == 0) {
402+
if (is_base_event_loop) {
391403
return 1;
392404
}
393405
}
@@ -443,7 +455,10 @@ call_soon(asyncio_state *state, PyObject *loop, PyObject *func, PyObject *arg,
443455
int is_base_event_loop_subclass =
444456
is_asyncio_base_event_loop_subclass(loop_type);
445457
int is_stdlib_base_event_loop =
446-
strcmp(loop_type->tp_name, "BaseEventLoop") == 0;
458+
is_asyncio_base_event_loop_type(loop_type);
459+
if (is_base_event_loop_subclass < 0 || is_stdlib_base_event_loop < 0) {
460+
return -1;
461+
}
447462
PyObject *call_soon_attr =
448463
PyDict_GetItemWithError(loop_type->tp_dict, &_Py_ID(call_soon));
449464
if (call_soon_attr == NULL && PyErr_Occurred()) {
@@ -454,15 +469,8 @@ call_soon(asyncio_state *state, PyObject *loop, PyObject *func, PyObject *arg,
454469
return -1;
455470
}
456471

457-
PyObject *module_name = PyDict_GetItemWithError(loop_type->tp_dict, &_Py_ID(__module__));
458-
if (module_name == NULL && PyErr_Occurred()) {
459-
return -1;
460-
}
461-
462472
int use_fastpath = (
463473
is_base_event_loop_subclass &&
464-
module_name != NULL &&
465-
PyUnicode_Check(module_name) &&
466474
// Only use the private fast path when the subclass keeps the public
467475
// call_soon() contract unchanged at both the type and instance level.
468476
!has_instance_call_soon_shadow &&

0 commit comments

Comments
 (0)