Skip to content

Commit a5a2967

Browse files
committed
Simplify asyncio loop fast path guard
1 parent 56d4b77 commit a5a2967

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
@@ -356,28 +356,40 @@ get_event_loop(asyncio_state *state)
356356
}
357357

358358

359+
static int
360+
is_asyncio_base_event_loop_type(PyTypeObject *loop_type)
361+
{
362+
if (strcmp(loop_type->tp_name, "BaseEventLoop") != 0) {
363+
return 0;
364+
}
365+
366+
PyObject *module_name =
367+
PyDict_GetItemWithError(loop_type->tp_dict, &_Py_ID(__module__));
368+
if (module_name == NULL) {
369+
if (PyErr_Occurred()) {
370+
return -1;
371+
}
372+
return 0;
373+
}
374+
375+
return (
376+
PyUnicode_Check(module_name) &&
377+
PyUnicode_CompareWithASCIIString(module_name, "asyncio.base_events") == 0
378+
);
379+
}
380+
359381
static int
360382
is_asyncio_base_event_loop_subclass(PyTypeObject *loop_type)
361383
{
362384
// The _asyncio module is imported from asyncio.events while
363385
// asyncio.base_events is still initializing, so we can't cache the
364386
// BaseEventLoop type during module init without creating an import cycle.
365387
for (PyTypeObject *base = loop_type; base != NULL; base = base->tp_base) {
366-
if (strcmp(base->tp_name, "BaseEventLoop") != 0) {
367-
continue;
368-
}
369-
370-
PyObject *module_name =
371-
PyDict_GetItemWithError(base->tp_dict, &_Py_ID(__module__));
372-
if (module_name == NULL) {
373-
if (PyErr_Occurred()) {
374-
return -1;
375-
}
376-
continue;
388+
int is_base_event_loop = is_asyncio_base_event_loop_type(base);
389+
if (is_base_event_loop < 0) {
390+
return -1;
377391
}
378-
379-
if (PyUnicode_Check(module_name) &&
380-
PyUnicode_CompareWithASCIIString(module_name, "asyncio.base_events") == 0) {
392+
if (is_base_event_loop) {
381393
return 1;
382394
}
383395
}
@@ -432,7 +444,10 @@ call_soon(asyncio_state *state, PyObject *loop, PyObject *func, PyObject *arg,
432444
int is_base_event_loop_subclass =
433445
is_asyncio_base_event_loop_subclass(loop_type);
434446
int is_stdlib_base_event_loop =
435-
strcmp(loop_type->tp_name, "BaseEventLoop") == 0;
447+
is_asyncio_base_event_loop_type(loop_type);
448+
if (is_base_event_loop_subclass < 0 || is_stdlib_base_event_loop < 0) {
449+
return -1;
450+
}
436451
PyObject *call_soon_attr =
437452
PyDict_GetItemWithError(loop_type->tp_dict, &_Py_ID(call_soon));
438453
if (call_soon_attr == NULL && PyErr_Occurred()) {
@@ -443,15 +458,8 @@ call_soon(asyncio_state *state, PyObject *loop, PyObject *func, PyObject *arg,
443458
return -1;
444459
}
445460

446-
PyObject *module_name = PyDict_GetItemWithError(loop_type->tp_dict, &_Py_ID(__module__));
447-
if (module_name == NULL && PyErr_Occurred()) {
448-
return -1;
449-
}
450-
451461
int use_fastpath = (
452462
is_base_event_loop_subclass &&
453-
module_name != NULL &&
454-
PyUnicode_Check(module_name) &&
455463
// Only use the private fast path when the subclass keeps the public
456464
// call_soon() contract unchanged at both the type and instance level.
457465
!has_instance_call_soon_shadow &&

0 commit comments

Comments
 (0)