bpo-34755: Add few minor optimizations in _asynciomodule.c. (GH-9455)
This commit is contained in:
parent
91e6c8717b
commit
fb3e9c00ed
|
@ -10,6 +10,7 @@ module _asyncio
|
|||
|
||||
/* identifiers used from some functions */
|
||||
_Py_IDENTIFIER(__asyncio_running_event_loop__);
|
||||
_Py_IDENTIFIER(_asyncio_future_blocking);
|
||||
_Py_IDENTIFIER(add_done_callback);
|
||||
_Py_IDENTIFIER(_all_tasks_compat);
|
||||
_Py_IDENTIFIER(call_soon);
|
||||
|
@ -22,7 +23,6 @@ _Py_IDENTIFIER(throw);
|
|||
|
||||
/* State of the _asyncio module */
|
||||
static PyObject *asyncio_mod;
|
||||
static PyObject *inspect_isgenerator;
|
||||
static PyObject *traceback_extract_stack;
|
||||
static PyObject *asyncio_get_event_loop_policy;
|
||||
static PyObject *asyncio_future_repr_info_func;
|
||||
|
@ -1304,13 +1304,8 @@ FutureObj_repr(FutureObj *fut)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *rstr = NULL;
|
||||
PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
|
||||
"__name__");
|
||||
if (type_name != NULL) {
|
||||
rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
|
||||
Py_DECREF(type_name);
|
||||
}
|
||||
PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
|
||||
_PyType_Name(Py_TYPE(fut)), rinfo_s);
|
||||
Py_DECREF(rinfo_s);
|
||||
return rstr;
|
||||
}
|
||||
|
@ -1326,7 +1321,6 @@ FutureObj_finalize(FutureObj *fut)
|
|||
|
||||
PyObject *error_type, *error_value, *error_traceback;
|
||||
PyObject *context;
|
||||
PyObject *type_name;
|
||||
PyObject *message = NULL;
|
||||
PyObject *func;
|
||||
|
||||
|
@ -1344,14 +1338,8 @@ FutureObj_finalize(FutureObj *fut)
|
|||
goto finally;
|
||||
}
|
||||
|
||||
type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
|
||||
if (type_name == NULL) {
|
||||
goto finally;
|
||||
}
|
||||
|
||||
message = PyUnicode_FromFormat(
|
||||
"%S exception was never retrieved", type_name);
|
||||
Py_DECREF(type_name);
|
||||
"%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
|
||||
if (message == NULL) {
|
||||
goto finally;
|
||||
}
|
||||
|
@ -1543,7 +1531,7 @@ static PyObject *
|
|||
FutureIter_send(futureiterobject *self, PyObject *unused)
|
||||
{
|
||||
/* Future.__iter__ doesn't care about values that are pushed to the
|
||||
* generator, it just returns "self.result().
|
||||
* generator, it just returns self.result().
|
||||
*/
|
||||
return FutureIter_iternext(self);
|
||||
}
|
||||
|
@ -2702,139 +2690,41 @@ set_exception:
|
|||
goto different_loop;
|
||||
}
|
||||
|
||||
if (fut->fut_blocking) {
|
||||
fut->fut_blocking = 0;
|
||||
|
||||
/* result.add_done_callback(task._wakeup) */
|
||||
wrapper = TaskWakeupMethWrapper_new(task);
|
||||
if (wrapper == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
res = future_add_done_callback(
|
||||
(FutureObj*)result, wrapper, task->task_context);
|
||||
Py_DECREF(wrapper);
|
||||
if (res == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
|
||||
/* task._fut_waiter = result */
|
||||
task->task_fut_waiter = result; /* no incref is necessary */
|
||||
|
||||
if (task->task_must_cancel) {
|
||||
PyObject *r;
|
||||
r = future_cancel(fut);
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (r == Py_True) {
|
||||
task->task_must_cancel = 0;
|
||||
}
|
||||
Py_DECREF(r);
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else {
|
||||
if (!fut->fut_blocking) {
|
||||
goto yield_insteadof_yf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if `result` is a Future-compatible object */
|
||||
o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
|
||||
if (o == NULL) {
|
||||
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
fut->fut_blocking = 0;
|
||||
|
||||
/* result.add_done_callback(task._wakeup) */
|
||||
wrapper = TaskWakeupMethWrapper_new(task);
|
||||
if (wrapper == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (o == Py_None) {
|
||||
Py_DECREF(o);
|
||||
res = future_add_done_callback(
|
||||
(FutureObj*)result, wrapper, task->task_context);
|
||||
Py_DECREF(wrapper);
|
||||
if (res == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
/* `result` is a Future-compatible object */
|
||||
PyObject *wrapper;
|
||||
PyObject *res;
|
||||
Py_DECREF(res);
|
||||
|
||||
int blocking = PyObject_IsTrue(o);
|
||||
Py_DECREF(o);
|
||||
if (blocking < 0) {
|
||||
goto fail;
|
||||
/* task._fut_waiter = result */
|
||||
task->task_fut_waiter = result; /* no incref is necessary */
|
||||
|
||||
if (task->task_must_cancel) {
|
||||
PyObject *r;
|
||||
r = future_cancel(fut);
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if `result` future is attached to a different loop */
|
||||
PyObject *oloop = get_future_loop(result);
|
||||
if (oloop == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
if (oloop != task->task_loop) {
|
||||
Py_DECREF(oloop);
|
||||
goto different_loop;
|
||||
}
|
||||
else {
|
||||
Py_DECREF(oloop);
|
||||
}
|
||||
|
||||
if (blocking) {
|
||||
/* result._asyncio_future_blocking = False */
|
||||
if (PyObject_SetAttrString(
|
||||
result, "_asyncio_future_blocking", Py_False) == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wrapper = TaskWakeupMethWrapper_new(task);
|
||||
if (wrapper == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* result.add_done_callback(task._wakeup) */
|
||||
PyObject *add_cb = _PyObject_GetAttrId(
|
||||
result, &PyId_add_done_callback);
|
||||
if (add_cb == NULL) {
|
||||
Py_DECREF(wrapper);
|
||||
goto fail;
|
||||
}
|
||||
PyObject *stack[2];
|
||||
stack[0] = wrapper;
|
||||
stack[1] = (PyObject *)task->task_context;
|
||||
res = _PyObject_FastCallKeywords(
|
||||
add_cb, stack, 1, context_kwname);
|
||||
Py_DECREF(add_cb);
|
||||
Py_DECREF(wrapper);
|
||||
if (res == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
|
||||
/* task._fut_waiter = result */
|
||||
task->task_fut_waiter = result; /* no incref is necessary */
|
||||
|
||||
if (task->task_must_cancel) {
|
||||
PyObject *r;
|
||||
int is_true;
|
||||
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
is_true = PyObject_IsTrue(r);
|
||||
Py_DECREF(r);
|
||||
if (is_true < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else if (is_true) {
|
||||
task->task_must_cancel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else {
|
||||
goto yield_insteadof_yf;
|
||||
if (r == Py_True) {
|
||||
task->task_must_cancel = 0;
|
||||
}
|
||||
Py_DECREF(r);
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* Check if `result` is None */
|
||||
|
@ -2846,19 +2736,96 @@ set_exception:
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Check if `result` is a Future-compatible object */
|
||||
if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if (o != NULL && o != Py_None) {
|
||||
/* `result` is a Future-compatible object */
|
||||
PyObject *wrapper;
|
||||
PyObject *res;
|
||||
|
||||
int blocking = PyObject_IsTrue(o);
|
||||
Py_DECREF(o);
|
||||
if (blocking < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check if `result` future is attached to a different loop */
|
||||
PyObject *oloop = get_future_loop(result);
|
||||
if (oloop == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
if (oloop != task->task_loop) {
|
||||
Py_DECREF(oloop);
|
||||
goto different_loop;
|
||||
}
|
||||
Py_DECREF(oloop);
|
||||
|
||||
if (!blocking) {
|
||||
goto yield_insteadof_yf;
|
||||
}
|
||||
|
||||
/* result._asyncio_future_blocking = False */
|
||||
if (_PyObject_SetAttrId(
|
||||
result, &PyId__asyncio_future_blocking, Py_False) == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wrapper = TaskWakeupMethWrapper_new(task);
|
||||
if (wrapper == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* result.add_done_callback(task._wakeup) */
|
||||
PyObject *add_cb = _PyObject_GetAttrId(
|
||||
result, &PyId_add_done_callback);
|
||||
if (add_cb == NULL) {
|
||||
Py_DECREF(wrapper);
|
||||
goto fail;
|
||||
}
|
||||
PyObject *stack[2];
|
||||
stack[0] = wrapper;
|
||||
stack[1] = (PyObject *)task->task_context;
|
||||
res = _PyObject_FastCallKeywords(
|
||||
add_cb, stack, 1, context_kwname);
|
||||
Py_DECREF(add_cb);
|
||||
Py_DECREF(wrapper);
|
||||
if (res == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
|
||||
/* task._fut_waiter = result */
|
||||
task->task_fut_waiter = result; /* no incref is necessary */
|
||||
|
||||
if (task->task_must_cancel) {
|
||||
PyObject *r;
|
||||
int is_true;
|
||||
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
is_true = PyObject_IsTrue(r);
|
||||
Py_DECREF(r);
|
||||
if (is_true < 0) {
|
||||
return NULL;
|
||||
}
|
||||
else if (is_true) {
|
||||
task->task_must_cancel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
Py_XDECREF(o);
|
||||
/* Check if `result` is a generator */
|
||||
o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
|
||||
if (o == NULL) {
|
||||
/* An exception in inspect.isgenerator */
|
||||
res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
|
||||
if (res < 0) {
|
||||
goto fail;
|
||||
}
|
||||
res = PyObject_IsTrue(o);
|
||||
Py_DECREF(o);
|
||||
if (res == -1) {
|
||||
/* An exception while checking if 'val' is True */
|
||||
goto fail;
|
||||
}
|
||||
if (res == 1) {
|
||||
if (res) {
|
||||
/* `result` is a generator */
|
||||
o = task_set_error_soon(
|
||||
task, PyExc_RuntimeError,
|
||||
|
@ -2922,7 +2889,7 @@ task_step(TaskObj *task, PyObject *exc)
|
|||
return NULL;
|
||||
}
|
||||
else {
|
||||
if(leave_task(task->task_loop, (PyObject*)task) < 0) {
|
||||
if (leave_task(task->task_loop, (PyObject*)task) < 0) {
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3237,7 +3204,6 @@ static void
|
|||
module_free(void *m)
|
||||
{
|
||||
Py_CLEAR(asyncio_mod);
|
||||
Py_CLEAR(inspect_isgenerator);
|
||||
Py_CLEAR(traceback_extract_stack);
|
||||
Py_CLEAR(asyncio_future_repr_info_func);
|
||||
Py_CLEAR(asyncio_get_event_loop_policy);
|
||||
|
@ -3278,15 +3244,10 @@ module_init(void)
|
|||
}
|
||||
|
||||
|
||||
context_kwname = PyTuple_New(1);
|
||||
context_kwname = Py_BuildValue("(s)", "context");
|
||||
if (context_kwname == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
PyObject *context_str = PyUnicode_FromString("context");
|
||||
if (context_str == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
PyTuple_SET_ITEM(context_kwname, 0, context_str);
|
||||
|
||||
#define WITH_MOD(NAME) \
|
||||
Py_CLEAR(module); \
|
||||
|
@ -3319,9 +3280,6 @@ module_init(void)
|
|||
WITH_MOD("asyncio.coroutines")
|
||||
GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
|
||||
|
||||
WITH_MOD("inspect")
|
||||
GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
|
||||
|
||||
WITH_MOD("traceback")
|
||||
GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
|
||||
|
||||
|
@ -3388,7 +3346,7 @@ PyInit__asyncio(void)
|
|||
if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
|
||||
if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyType_Ready(&TaskType) < 0) {
|
||||
|
|
Loading…
Reference in New Issue