summaryrefslogtreecommitdiff
path: root/Modules
diff options
context:
space:
mode:
authorVladimir Matveev <vladima@fb.com>2020-11-10 12:09:55 -0800
committerGitHub <noreply@github.com>2020-11-10 12:09:55 -0800
commit1e996c3a3b51e9c6f1f4cea8a6dbcf3bcb865060 (patch)
tree3f3ffd5d90532c6f4b1ec013919e3677d63dd21c /Modules
parente59b2deffde61e5641cabd65034fa11b4db898ba (diff)
downloadcpython-git-1e996c3a3b51e9c6f1f4cea8a6dbcf3bcb865060.tar.gz
bpo-42085: Introduce dedicated entry in PyAsyncMethods for sending values (#22780)
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_asynciomodule.c56
-rw-r--r--Modules/_testcapimodule.c3
2 files changed, 47 insertions, 12 deletions
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 90d288f739..d1d0f6bc75 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -1479,7 +1479,8 @@ future_cls_getitem(PyObject *cls, PyObject *type)
static PyAsyncMethods FutureType_as_async = {
(unaryfunc)future_new_iter, /* am_await */
0, /* am_aiter */
- 0 /* am_anext */
+ 0, /* am_anext */
+ 0, /* am_send */
};
static PyMethodDef FutureType_methods[] = {
@@ -1597,37 +1598,60 @@ FutureIter_dealloc(futureiterobject *it)
}
}
-static PyObject *
-FutureIter_iternext(futureiterobject *it)
+static PySendResult
+FutureIter_am_send(futureiterobject *it,
+ PyObject *Py_UNUSED(arg),
+ PyObject **result)
{
+ /* arg is unused, see the comment on FutureIter_send for clarification */
+
PyObject *res;
FutureObj *fut = it->future;
+ *result = NULL;
if (fut == NULL) {
- return NULL;
+ return PYGEN_ERROR;
}
if (fut->fut_state == STATE_PENDING) {
if (!fut->fut_blocking) {
fut->fut_blocking = 1;
Py_INCREF(fut);
- return (PyObject *)fut;
+ *result = (PyObject *)fut;
+ return PYGEN_NEXT;
}
PyErr_SetString(PyExc_RuntimeError,
"await wasn't used with future");
- return NULL;
+ return PYGEN_ERROR;
}
it->future = NULL;
res = _asyncio_Future_result_impl(fut);
if (res != NULL) {
- /* The result of the Future is not an exception. */
- (void)_PyGen_SetStopIterationValue(res);
- Py_DECREF(res);
+ *result = res;
+ return PYGEN_RETURN;
}
Py_DECREF(fut);
- return NULL;
+ return PYGEN_ERROR;
+}
+
+static PyObject *
+FutureIter_iternext(futureiterobject *it)
+{
+ PyObject *result;
+ switch (FutureIter_am_send(it, Py_None, &result)) {
+ case PYGEN_RETURN:
+ (void)_PyGen_SetStopIterationValue(result);
+ Py_DECREF(result);
+ return NULL;
+ case PYGEN_NEXT:
+ return result;
+ case PYGEN_ERROR:
+ return NULL;
+ default:
+ Py_UNREACHABLE();
+ }
}
static PyObject *
@@ -1716,14 +1740,24 @@ static PyMethodDef FutureIter_methods[] = {
{NULL, NULL} /* Sentinel */
};
+static PyAsyncMethods FutureIterType_as_async = {
+ 0, /* am_await */
+ 0, /* am_aiter */
+ 0, /* am_anext */
+ (sendfunc)FutureIter_am_send, /* am_send */
+};
+
+
static PyTypeObject FutureIterType = {
PyVarObject_HEAD_INIT(NULL, 0)
"_asyncio.FutureIter",
.tp_basicsize = sizeof(futureiterobject),
.tp_itemsize = 0,
.tp_dealloc = (destructor)FutureIter_dealloc,
+ .tp_as_async = &FutureIterType_as_async,
.tp_getattro = PyObject_GenericGetAttr,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_HAVE_AM_SEND,
.tp_traverse = (traverseproc)FutureIter_traverse,
.tp_iter = PyObject_SelfIter,
.tp_iternext = (iternextfunc)FutureIter_iternext,
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 22d20d220d..4382b642dc 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -6142,7 +6142,8 @@ awaitObject_await(awaitObject *ao)
static PyAsyncMethods awaitType_as_async = {
(unaryfunc)awaitObject_await, /* am_await */
0, /* am_aiter */
- 0 /* am_anext */
+ 0, /* am_anext */
+ 0, /* am_send */
};