Skip to content

Commit

Permalink
Make pairwise_next safe for free-threading
Browse files Browse the repository at this point in the history
  • Loading branch information
eendebakpt committed Oct 13, 2024
1 parent cb8e599 commit d7cbe16
Showing 1 changed file with 17 additions and 10 deletions.
27 changes: 17 additions & 10 deletions Modules/itertoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,37 +327,43 @@ pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg)
static PyObject *
pairwise_next(pairwiseobject *po)
{
PyObject *it = po->it;
PyObject *old = po->old;
PyObject *new, *result;

PyObject *it = Py_XNewRef(po->it);
if (it == NULL) {
return NULL;
}

PyObject *old = Py_XNewRef(po->old);
PyObject *new, *result;

if (old == NULL) {
old = (*Py_TYPE(it)->tp_iternext)(it);
Py_XSETREF(po->old, old);
if (old == NULL) {
Py_CLEAR(po->it);
Py_DECREF(it);
return NULL;
}
it = po->it;
if (it == NULL) {
Py_XSETREF(po->old, Py_NewRef(old));
if (po->it == NULL) {
// for re-entrant calls to pairwise next. the actual behavior is not important and this does not avoid any bugs (or does it?)
// the reason for having it is to make the behaviour equal to the python implementation behavior
Py_CLEAR(po->old);
Py_DECREF(old);
Py_DECREF(it);
return NULL;
}
}
Py_INCREF(old);

new = (*Py_TYPE(it)->tp_iternext)(it);
if (new == NULL) {
Py_CLEAR(po->it);
Py_CLEAR(po->old);
Py_DECREF(it);
Py_DECREF(old);
return NULL;
}

result = po->result;
if (Py_REFCNT(result) == 1) {
if (_PyObject_IsUniquelyReferenced(result)) {
Py_INCREF(result);
PyObject *last_old = PyTuple_GET_ITEM(result, 0);
PyObject *last_new = PyTuple_GET_ITEM(result, 1);
Expand All @@ -380,7 +386,8 @@ pairwise_next(pairwiseobject *po)
}

Py_XSETREF(po->old, new);
Py_DECREF(old);
Py_DECREF(old); // instead of the decref here we could borrow the reference above
Py_DECREF(it);
return result;
}

Expand Down

0 comments on commit d7cbe16

Please sign in to comment.