Skip to content

Commit dba67de

Browse files
add comments
1 parent aefd1a6 commit dba67de

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

Objects/genobject.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,12 @@ async_gen_try_set_state(int8_t *state, int8_t *expected, int8_t new_state)
16201620

16211621
// Try to transition the async generator to the running state.
16221622
// Returns false if it is already running.
1623+
//
1624+
// There are two ways to concurrently iterate an async generator: by
1625+
// sharing a single asend()/athrow() object across threads, or with
1626+
// multiple asend()/athrow() objects sending to the same generator.
1627+
// The CAS on ags_state/agt_state handles the first case; the CAS on
1628+
// ag_running_async here handles the second.
16231629
static bool
16241630
async_gen_try_claim_running(PyAsyncGenObject *agen)
16251631
{
@@ -2026,7 +2032,9 @@ async_gen_asend_send(PyObject *self, PyObject *arg)
20262032
} while (!_Py_ASYNC_GEN_TRY_SET_STATE(o->ags_state, state,
20272033
AWAITABLE_STATE_ITER));
20282034

2029-
// INIT -> ITER transition succeeded, this is the first send.
2035+
// The transition above only guards this object, the generator may
2036+
// still be running through another asend()/athrow() object so
2037+
// try to claim it before running.
20302038
if (!async_gen_try_claim_running(o->ags_gen)) {
20312039
FT_ATOMIC_STORE_INT8_RELAXED(o->ags_state, AWAITABLE_STATE_CLOSED);
20322040
PyErr_SetString(
@@ -2092,6 +2100,9 @@ async_gen_asend_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
20922100
} while (!_Py_ASYNC_GEN_TRY_SET_STATE(o->ags_state, state,
20932101
AWAITABLE_STATE_ITER));
20942102

2103+
// The transition above only guards this object, the generator may
2104+
// still be running through another asend()/athrow() object so
2105+
// try to claim it before running.
20952106
if (!async_gen_try_claim_running(o->ags_gen)) {
20962107
FT_ATOMIC_STORE_INT8_RELAXED(o->ags_state, AWAITABLE_STATE_CLOSED);
20972108
PyErr_SetString(
@@ -2380,7 +2391,9 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
23802391
} while (!_Py_ASYNC_GEN_TRY_SET_STATE(o->agt_state, state,
23812392
AWAITABLE_STATE_ITER));
23822393

2383-
// INIT -> ITER transition succeeded, this is the first send.
2394+
// The transition above only guards this object, the generator may
2395+
// still be running through another asend()/athrow() object so
2396+
// try to claim it before running.
23842397
if (!async_gen_try_claim_running(o->agt_gen)) {
23852398
FT_ATOMIC_STORE_INT8_RELAXED(o->agt_state, AWAITABLE_STATE_CLOSED);
23862399
if (o->agt_typ == NULL) {
@@ -2506,6 +2519,9 @@ async_gen_athrow_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
25062519
} while (!_Py_ASYNC_GEN_TRY_SET_STATE(o->agt_state, state,
25072520
AWAITABLE_STATE_ITER));
25082521

2522+
// The transition above only guards this object, the generator may
2523+
// still be running through another asend()/athrow() object so
2524+
// try to claim it before running.
25092525
if (!async_gen_try_claim_running(o->agt_gen)) {
25102526
FT_ATOMIC_STORE_INT8_RELAXED(o->agt_state, AWAITABLE_STATE_CLOSED);
25112527
if (o->agt_typ == NULL) {

0 commit comments

Comments
 (0)