@@ -159,13 +159,30 @@ gen_dealloc(PyGenObject *gen)
159159 * was not faster, but considerably slower than this solution.
160160 */
161161
162- static PyObject * gen_iternext_callback (PyFrameObject * f , int exc , PyObject * result );
162+ /* Like gen_send_ex, additionally pass ob3 into the callback function. */
163+ static PyObject *
164+ gen_send_ex2 (PyGenObject * gen , PyObject * arg , int exc , int closing , PyObject * ob3 );
165+
166+ /* callback for (async) generators and coroutines. */
167+ static PyObject *
168+ gen_iternext_callback (PyFrameObject * f , int exc , PyObject * result );
169+
170+ /* Additional callback-code for async generators. */
171+ static PyObject *
172+ async_gen_asend_send_end (PyAsyncGenObject * gen , PyObject * asend , PyObject * result );
163173#endif
164174
175+
165176static PyObject *
166177gen_send_ex (PyGenObject * gen , PyObject * arg , int exc , int closing )
167178{
168179#ifdef STACKLESS
180+ return gen_send_ex2 (gen , arg , exc , closing , NULL );
181+ }
182+
183+ static PyObject *
184+ gen_send_ex2 (PyGenObject * gen , PyObject * arg , int exc , int closing , PyObject * ob3 )
185+ {
169186 STACKLESS_GETARG ();
170187 PyFrameObject * stopframe ;
171188#endif
@@ -249,6 +266,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
249266 assert (f -> f_back -> f_back == NULL );
250267 assert (((PyCFrameObject * )f -> f_back )-> ob1 == NULL );
251268 assert (((PyCFrameObject * )f -> f_back )-> ob2 == NULL );
269+ assert (((PyCFrameObject * )f -> f_back )-> ob3 == NULL );
252270
253271 if (f -> f_lasti != -1 )
254272#else
@@ -295,8 +313,10 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
295313
296314 Py_INCREF (gen );
297315 Py_XINCREF (arg );
316+ Py_XINCREF (ob3 );
298317 ((PyCFrameObject * ) f -> f_back )-> ob1 = (PyObject * ) gen ;
299318 ((PyCFrameObject * ) f -> f_back )-> ob2 = arg ;
319+ ((PyCFrameObject * ) f -> f_back )-> ob3 = ob3 ;
300320
301321 if (exc )
302322 result = NULL ;
@@ -326,12 +346,14 @@ gen_iternext_callback(PyFrameObject *f, int exc, PyObject *result)
326346 PyCFrameObject * cf = (PyCFrameObject * ) f ;
327347 PyGenObject * gen = (PyGenObject * ) cf -> ob1 ;
328348 PyObject * arg = cf -> ob2 ;
349+ PyObject * ob3 = cf -> ob3 ;
329350
330351 /* We hold references to things in the cframe, if we release it
331352 before we clear the references, they get incorrectly and
332353 prematurely freed. */
333354 cf -> ob1 = NULL ;
334355 cf -> ob2 = NULL ;
356+ cf -> ob3 = NULL ;
335357
336358 f = gen -> gi_frame ;
337359 /* Check, that this cframe belongs to gen */
@@ -400,8 +422,13 @@ gen_iternext_callback(PyFrameObject *f, int exc, PyObject *result)
400422 Py_DECREF (f );
401423 }
402424#ifdef STACKLESS
425+ if (ob3 && PyAsyncGen_CheckExact (gen )) {
426+ result = async_gen_asend_send_end ((PyAsyncGenObject * )gen , ob3 , result );
427+ }
428+
403429 Py_DECREF (gen );
404430 Py_XDECREF (arg );
431+ Py_XDECREF (ob3 );
405432#endif
406433 return result ;
407434}
@@ -839,7 +866,7 @@ static PyMemberDef gen_memberlist[] = {
839866};
840867
841868static PyMethodDef gen_methods [] = {
842- {"send" ,(PyCFunction )_PyGen_Send , METH_O , send_doc },
869+ {"send" ,(PyCFunction )_PyGen_Send , METH_O | METH_STACKLESS , send_doc },
843870 {"throw" ,(PyCFunction )gen_throw , METH_VARARGS , throw_doc },
844871 {"close" ,(PyCFunction )gen_close , METH_NOARGS , close_doc },
845872 {NULL , NULL } /* Sentinel */
@@ -1092,7 +1119,7 @@ PyDoc_STRVAR(coro_close_doc,
10921119"close() -> raise GeneratorExit inside coroutine." );
10931120
10941121static PyMethodDef coro_methods [] = {
1095- {"send" ,(PyCFunction )_PyGen_Send , METH_O , coro_send_doc },
1122+ {"send" ,(PyCFunction )_PyGen_Send , METH_O | METH_STACKLESS , coro_send_doc },
10961123 {"throw" ,(PyCFunction )gen_throw , METH_VARARGS , coro_throw_doc },
10971124 {"close" ,(PyCFunction )gen_close , METH_NOARGS , coro_close_doc },
10981125 {NULL , NULL } /* Sentinel */
@@ -1197,7 +1224,7 @@ coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
11971224}
11981225
11991226static PyMethodDef coro_wrapper_methods [] = {
1200- {"send" ,(PyCFunction )coro_wrapper_send , METH_O , coro_send_doc },
1227+ {"send" ,(PyCFunction )coro_wrapper_send , METH_O | METH_STACKLESS , coro_send_doc },
12011228 {"throw" ,(PyCFunction )coro_wrapper_throw , METH_VARARGS , coro_throw_doc },
12021229 {"close" ,(PyCFunction )coro_wrapper_close , METH_NOARGS , coro_close_doc },
12031230 {NULL , NULL } /* Sentinel */
@@ -1245,6 +1272,8 @@ PyTypeObject _PyCoroWrapper_Type = {
12451272 0 , /* tp_free */
12461273};
12471274
1275+ STACKLESS_DECLARE_METHOD (& _PyCoroWrapper_Type , tp_iternext );
1276+
12481277static PyObject *
12491278compute_cr_origin (int origin_depth )
12501279{
@@ -1666,6 +1695,7 @@ async_gen_asend_traverse(PyAsyncGenASend *o, visitproc visit, void *arg)
16661695static PyObject *
16671696async_gen_asend_send (PyAsyncGenASend * o , PyObject * arg )
16681697{
1698+ STACKLESS_GETARG ();
16691699 PyObject * result ;
16701700
16711701 if (o -> ags_state == AWAITABLE_STATE_CLOSED ) {
@@ -1680,6 +1710,16 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
16801710 o -> ags_state = AWAITABLE_STATE_ITER ;
16811711 }
16821712
1713+ #ifdef STACKLESS
1714+ if (stackless ) {
1715+ STACKLESS_PROMOTE_ALL ();
1716+ result = gen_send_ex2 ((PyGenObject * )o -> ags_gen , arg , 0 , 0 , (PyObject * )o );
1717+ STACKLESS_ASSERT ();
1718+ if (STACKLESS_UNWINDING (result ))
1719+ return result ;
1720+ }
1721+ else
1722+ #endif
16831723 result = gen_send_ex ((PyGenObject * )o -> ags_gen , arg , 0 , 0 );
16841724 result = async_gen_unwrap_value (o -> ags_gen , result );
16851725
@@ -1690,6 +1730,22 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
16901730 return result ;
16911731}
16921732
1733+ #ifdef STACKLESS
1734+ static PyObject *
1735+ async_gen_asend_send_end (PyAsyncGenObject * gen , PyObject * asend , PyObject * result )
1736+ {
1737+ PyAsyncGenASend * o = (PyAsyncGenASend * ) asend ;
1738+ assert (o -> ags_gen == gen );
1739+
1740+ result = async_gen_unwrap_value (o -> ags_gen , result );
1741+
1742+ if (result == NULL ) {
1743+ o -> ags_state = AWAITABLE_STATE_CLOSED ;
1744+ }
1745+
1746+ return result ;
1747+ }
1748+ #endif
16931749
16941750static PyObject *
16951751async_gen_asend_iternext (PyAsyncGenASend * o )
@@ -1728,7 +1784,7 @@ async_gen_asend_close(PyAsyncGenASend *o, PyObject *args)
17281784
17291785
17301786static PyMethodDef async_gen_asend_methods [] = {
1731- {"send" , (PyCFunction )async_gen_asend_send , METH_O , send_doc },
1787+ {"send" , (PyCFunction )async_gen_asend_send , METH_O | METH_STACKLESS , send_doc },
17321788 {"throw" , (PyCFunction )async_gen_asend_throw , METH_VARARGS , throw_doc },
17331789 {"close" , (PyCFunction )async_gen_asend_close , METH_NOARGS , close_doc },
17341790 {NULL , NULL } /* Sentinel */
@@ -1784,6 +1840,8 @@ PyTypeObject _PyAsyncGenASend_Type = {
17841840 0 , /* tp_new */
17851841};
17861842
1843+ STACKLESS_DECLARE_METHOD (& _PyAsyncGenASend_Type , tp_iternext );
1844+
17871845
17881846static PyObject *
17891847async_gen_asend_new (PyAsyncGenObject * gen , PyObject * sendval )
0 commit comments