@@ -439,20 +439,22 @@ reversed_next(PyObject *op)
439439{
440440 reversedobject * ro = _reversedobject_CAST (op );
441441 PyObject * item ;
442- Py_ssize_t index = ro -> index ;
442+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED ( ro -> index ) ;
443443
444444 if (index >= 0 ) {
445445 item = PySequence_GetItem (ro -> seq , index );
446446 if (item != NULL ) {
447- ro -> index -- ;
447+ FT_ATOMIC_STORE_SSIZE_RELAXED ( ro -> index , index - 1 ) ;
448448 return item ;
449449 }
450450 if (PyErr_ExceptionMatches (PyExc_IndexError ) ||
451451 PyErr_ExceptionMatches (PyExc_StopIteration ))
452452 PyErr_Clear ();
453453 }
454- ro -> index = -1 ;
454+ FT_ATOMIC_STORE_SSIZE_RELAXED (ro -> index , -1 );
455+ #ifndef Py_GIL_DISABLED
455456 Py_CLEAR (ro -> seq );
457+ #endif
456458 return NULL ;
457459}
458460
@@ -461,13 +463,15 @@ reversed_len(PyObject *op, PyObject *Py_UNUSED(ignored))
461463{
462464 reversedobject * ro = _reversedobject_CAST (op );
463465 Py_ssize_t position , seqsize ;
466+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED (ro -> index );
464467
465- if (ro -> seq == NULL )
468+ if (index == -1 )
466469 return PyLong_FromLong (0 );
470+ assert (ro -> seq != NULL );
467471 seqsize = PySequence_Size (ro -> seq );
468472 if (seqsize == -1 )
469473 return NULL ;
470- position = ro -> index + 1 ;
474+ position = index + 1 ;
471475 return PyLong_FromSsize_t ((seqsize < position ) ? 0 : position );
472476}
473477
@@ -477,10 +481,13 @@ static PyObject *
477481reversed_reduce (PyObject * op , PyObject * Py_UNUSED (ignored ))
478482{
479483 reversedobject * ro = _reversedobject_CAST (op );
480- if (ro -> seq )
484+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED (ro -> index );
485+ if (index != -1 ) {
481486 return Py_BuildValue ("O(O)n" , Py_TYPE (ro ), ro -> seq , ro -> index );
482- else
487+ }
488+ else {
483489 return Py_BuildValue ("O(())" , Py_TYPE (ro ));
490+ }
484491}
485492
486493static PyObject *
@@ -490,15 +497,19 @@ reversed_setstate(PyObject *op, PyObject *state)
490497 Py_ssize_t index = PyLong_AsSsize_t (state );
491498 if (index == -1 && PyErr_Occurred ())
492499 return NULL ;
493- if (ro -> seq != 0 ) {
500+ Py_ssize_t ro_index = FT_ATOMIC_LOAD_SSIZE_RELAXED (ro -> index );
501+ // if the iterator is exhausted we do not set the state
502+ // this is for backwards compatibility reasons. in practice this situation
503+ // will not occur, see gh-120971
504+ if (ro_index != -1 ) {
494505 Py_ssize_t n = PySequence_Size (ro -> seq );
495506 if (n < 0 )
496507 return NULL ;
497508 if (index < -1 )
498509 index = -1 ;
499510 else if (index > n - 1 )
500511 index = n - 1 ;
501- ro -> index = index ;
512+ FT_ATOMIC_STORE_SSIZE_RELAXED ( ro -> index , index ) ;
502513 }
503514 Py_RETURN_NONE ;
504515}
0 commit comments