@@ -159,13 +159,30 @@ gen_dealloc(PyGenObject *gen)
159
159
* was not faster, but considerably slower than this solution.
160
160
*/
161
161
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 );
163
173
#endif
164
174
175
+
165
176
static PyObject *
166
177
gen_send_ex (PyGenObject * gen , PyObject * arg , int exc , int closing )
167
178
{
168
179
#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
+ {
169
186
STACKLESS_GETARG ();
170
187
PyFrameObject * stopframe ;
171
188
#endif
@@ -249,6 +266,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
249
266
assert (f -> f_back -> f_back == NULL );
250
267
assert (((PyCFrameObject * )f -> f_back )-> ob1 == NULL );
251
268
assert (((PyCFrameObject * )f -> f_back )-> ob2 == NULL );
269
+ assert (((PyCFrameObject * )f -> f_back )-> ob3 == NULL );
252
270
253
271
if (f -> f_lasti != -1 )
254
272
#else
@@ -295,8 +313,10 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
295
313
296
314
Py_INCREF (gen );
297
315
Py_XINCREF (arg );
316
+ Py_XINCREF (ob3 );
298
317
((PyCFrameObject * ) f -> f_back )-> ob1 = (PyObject * ) gen ;
299
318
((PyCFrameObject * ) f -> f_back )-> ob2 = arg ;
319
+ ((PyCFrameObject * ) f -> f_back )-> ob3 = ob3 ;
300
320
301
321
if (exc )
302
322
result = NULL ;
@@ -326,12 +346,14 @@ gen_iternext_callback(PyFrameObject *f, int exc, PyObject *result)
326
346
PyCFrameObject * cf = (PyCFrameObject * ) f ;
327
347
PyGenObject * gen = (PyGenObject * ) cf -> ob1 ;
328
348
PyObject * arg = cf -> ob2 ;
349
+ PyObject * ob3 = cf -> ob3 ;
329
350
330
351
/* We hold references to things in the cframe, if we release it
331
352
before we clear the references, they get incorrectly and
332
353
prematurely freed. */
333
354
cf -> ob1 = NULL ;
334
355
cf -> ob2 = NULL ;
356
+ cf -> ob3 = NULL ;
335
357
336
358
f = gen -> gi_frame ;
337
359
/* Check, that this cframe belongs to gen */
@@ -400,8 +422,13 @@ gen_iternext_callback(PyFrameObject *f, int exc, PyObject *result)
400
422
Py_DECREF (f );
401
423
}
402
424
#ifdef STACKLESS
425
+ if (ob3 && PyAsyncGen_CheckExact (gen )) {
426
+ result = async_gen_asend_send_end ((PyAsyncGenObject * )gen , ob3 , result );
427
+ }
428
+
403
429
Py_DECREF (gen );
404
430
Py_XDECREF (arg );
431
+ Py_XDECREF (ob3 );
405
432
#endif
406
433
return result ;
407
434
}
@@ -839,7 +866,7 @@ static PyMemberDef gen_memberlist[] = {
839
866
};
840
867
841
868
static PyMethodDef gen_methods [] = {
842
- {"send" ,(PyCFunction )_PyGen_Send , METH_O , send_doc },
869
+ {"send" ,(PyCFunction )_PyGen_Send , METH_O | METH_STACKLESS , send_doc },
843
870
{"throw" ,(PyCFunction )gen_throw , METH_VARARGS , throw_doc },
844
871
{"close" ,(PyCFunction )gen_close , METH_NOARGS , close_doc },
845
872
{NULL , NULL } /* Sentinel */
@@ -1092,7 +1119,7 @@ PyDoc_STRVAR(coro_close_doc,
1092
1119
"close() -> raise GeneratorExit inside coroutine." );
1093
1120
1094
1121
static 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 },
1096
1123
{"throw" ,(PyCFunction )gen_throw , METH_VARARGS , coro_throw_doc },
1097
1124
{"close" ,(PyCFunction )gen_close , METH_NOARGS , coro_close_doc },
1098
1125
{NULL , NULL } /* Sentinel */
@@ -1197,7 +1224,7 @@ coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
1197
1224
}
1198
1225
1199
1226
static 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 },
1201
1228
{"throw" ,(PyCFunction )coro_wrapper_throw , METH_VARARGS , coro_throw_doc },
1202
1229
{"close" ,(PyCFunction )coro_wrapper_close , METH_NOARGS , coro_close_doc },
1203
1230
{NULL , NULL } /* Sentinel */
@@ -1245,6 +1272,8 @@ PyTypeObject _PyCoroWrapper_Type = {
1245
1272
0 , /* tp_free */
1246
1273
};
1247
1274
1275
+ STACKLESS_DECLARE_METHOD (& _PyCoroWrapper_Type , tp_iternext );
1276
+
1248
1277
static PyObject *
1249
1278
compute_cr_origin (int origin_depth )
1250
1279
{
@@ -1666,6 +1695,7 @@ async_gen_asend_traverse(PyAsyncGenASend *o, visitproc visit, void *arg)
1666
1695
static PyObject *
1667
1696
async_gen_asend_send (PyAsyncGenASend * o , PyObject * arg )
1668
1697
{
1698
+ STACKLESS_GETARG ();
1669
1699
PyObject * result ;
1670
1700
1671
1701
if (o -> ags_state == AWAITABLE_STATE_CLOSED ) {
@@ -1680,6 +1710,16 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
1680
1710
o -> ags_state = AWAITABLE_STATE_ITER ;
1681
1711
}
1682
1712
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
1683
1723
result = gen_send_ex ((PyGenObject * )o -> ags_gen , arg , 0 , 0 );
1684
1724
result = async_gen_unwrap_value (o -> ags_gen , result );
1685
1725
@@ -1690,6 +1730,22 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
1690
1730
return result ;
1691
1731
}
1692
1732
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
1693
1749
1694
1750
static PyObject *
1695
1751
async_gen_asend_iternext (PyAsyncGenASend * o )
@@ -1728,7 +1784,7 @@ async_gen_asend_close(PyAsyncGenASend *o, PyObject *args)
1728
1784
1729
1785
1730
1786
static 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 },
1732
1788
{"throw" , (PyCFunction )async_gen_asend_throw , METH_VARARGS , throw_doc },
1733
1789
{"close" , (PyCFunction )async_gen_asend_close , METH_NOARGS , close_doc },
1734
1790
{NULL , NULL } /* Sentinel */
@@ -1784,6 +1840,8 @@ PyTypeObject _PyAsyncGenASend_Type = {
1784
1840
0 , /* tp_new */
1785
1841
};
1786
1842
1843
+ STACKLESS_DECLARE_METHOD (& _PyAsyncGenASend_Type , tp_iternext );
1844
+
1787
1845
1788
1846
static PyObject *
1789
1847
async_gen_asend_new (PyAsyncGenObject * gen , PyObject * sendval )
0 commit comments