@@ -1057,16 +1057,16 @@ setiter_len(PyObject *op, PyObject *Py_UNUSED(ignored))
10571057 setiterobject * si = (setiterobject * )op ;
10581058 Py_ssize_t len = 0 ;
10591059#ifdef Py_GIL_DISABLED
1060- PyObject * so_obj = FT_ATOMIC_LOAD_PTR_ACQUIRE (si -> si_set );
1061- if (so_obj != NULL ) {
1062- /* Turn borrowed si->si_set into a strong ref safely. */
1063- if (_Py_TryIncrefCompare ((PyObject * * )& si -> si_set , so_obj )) {
1064- PySetObject * so = (PySetObject * )so_obj ;
1065- if (si -> si_used == FT_ATOMIC_LOAD_SSIZE_RELAXED (so -> used )) {
1066- len = si -> len ;
1067- }
1068- Py_DECREF (so_obj );
1060+ PySetObject * so = si -> si_set ;
1061+ if (so != NULL ) {
1062+ Py_BEGIN_CRITICAL_SECTION (so );
1063+ Py_ssize_t pos = FT_ATOMIC_LOAD_SSIZE_RELAXED (si -> si_pos );
1064+ if (pos >= 0 &&
1065+ si -> si_used == FT_ATOMIC_LOAD_SSIZE_RELAXED (so -> used ))
1066+ {
1067+ len = si -> len ;
10691068 }
1069+ Py_END_CRITICAL_SECTION ();
10701070 }
10711071#else
10721072 if (si -> si_set != NULL && si -> si_used == si -> si_set -> used ) {
@@ -1126,7 +1126,16 @@ static PyObject *setiter_iternext(PyObject *self)
11261126 }
11271127
11281128 Py_BEGIN_CRITICAL_SECTION (so );
1129+ #ifdef Py_GIL_DISABLED
1130+ /* si_pos may be read outside the lock; keep it atomic in FT builds */
1131+ i = FT_ATOMIC_LOAD_SSIZE_RELAXED (si -> si_pos );
1132+ if (i < 0 ) {
1133+ /* iterator already exhausted */
1134+ goto done ;
1135+ }
1136+ #else
11291137 i = si -> si_pos ;
1138+ #endif
11301139 assert (i >=0 );
11311140 entry = so -> table ;
11321141 mask = so -> mask ;
@@ -1135,19 +1144,30 @@ static PyObject *setiter_iternext(PyObject *self)
11351144 }
11361145 if (i <= mask ) {
11371146 key = Py_NewRef (entry [i ].key );
1147+ #ifdef Py_GIL_DISABLED
1148+ FT_ATOMIC_STORE_SSIZE_RELAXED (si -> si_pos , i + 1 );
1149+ #else
1150+ si -> si_pos = i + 1 ;
1151+ #endif
1152+ si -> len -- ;
11381153 }
1139- Py_END_CRITICAL_SECTION ();
1140- si -> si_pos = i + 1 ;
1141- if (key == NULL ) {
1154+ else {
11421155#ifdef Py_GIL_DISABLED
1143- FT_ATOMIC_STORE_PTR_RELEASE (si -> si_set , NULL );
1156+ /* free-threaded: keep si_set; just mark exhausted */
1157+ FT_ATOMIC_STORE_SSIZE_RELAXED (si -> si_pos , -1 );
1158+ si -> len = 0 ;
11441159#else
11451160 si -> si_set = NULL ;
11461161#endif
1162+ }
1163+ done :
1164+ Py_END_CRITICAL_SECTION ();
1165+ if (key == NULL ) {
1166+ #ifndef Py_GIL_DISABLED
11471167 Py_DECREF (so );
1168+ #endif
11481169 return NULL ;
11491170 }
1150- si -> len -- ;
11511171 return key ;
11521172}
11531173
0 commit comments