File tree Expand file tree Collapse file tree 2 files changed +42
-9
lines changed 
Lib/test/test_free_threading Expand file tree Collapse file tree 2 files changed +42
-9
lines changed Original file line number Diff line number Diff line change 11import  unittest 
22from  threading  import  Thread , Barrier 
3- from  itertools  import  batched 
3+ from  itertools  import  batched ,  cycle 
44from  test .support  import  threading_helper 
55
66
77threading_helper .requires_working_threading (module = True )
88
9- class  EnumerateThreading (unittest .TestCase ):
9+ class  ItertoolsThreading (unittest .TestCase ):
1010
1111    @threading_helper .reap_threads  
12-     def  test_threading (self ):
12+     def  test_batched (self ):
1313        number_of_threads  =  10 
1414        number_of_iterations  =  20 
1515        barrier  =  Barrier (number_of_threads )
@@ -34,5 +34,31 @@ def work(it):
3434
3535            barrier .reset ()
3636
37+     @threading_helper .reap_threads  
38+     def  test_cycle (self ):
39+         number_of_threads  =  6 
40+         number_of_iterations  =  10 
41+         number_of_cycles  =  400 
42+ 
43+         barrier  =  Barrier (number_of_threads )
44+         def  work (it ):
45+             barrier .wait ()
46+             for  _  in  range (number_of_cycles ):
47+                 _  =  next (it )
48+ 
49+         data  =  (1 , 2 , 3 , 4 )
50+         for  it  in  range (number_of_iterations ):
51+             cycle_iterator  =  cycle (data )
52+             worker_threads  =  []
53+             for  ii  in  range (number_of_threads ):
54+                 worker_threads .append (
55+                     Thread (target = work , args = [cycle_iterator ]))
56+ 
57+             with  threading_helper .start_threads (worker_threads ):
58+                 pass 
59+ 
60+             barrier .reset ()
61+ 
62+ 
3763if  __name__  ==  "__main__" :
3864    unittest .main ()
Original file line number Diff line number Diff line change @@ -1166,7 +1166,7 @@ itertools_cycle_impl(PyTypeObject *type, PyObject *iterable)
11661166    }
11671167    lz -> it  =  it ;
11681168    lz -> saved  =  saved ;
1169-     lz -> index  =  0 ;
1169+     lz -> index  =  -1 ;
11701170
11711171    return  (PyObject  * )lz ;
11721172}
@@ -1199,7 +1199,9 @@ cycle_next(PyObject *op)
11991199    cycleobject  * lz  =  cycleobject_CAST (op );
12001200    PyObject  * item ;
12011201
1202-     if  (lz -> it  !=  NULL ) {
1202+     Py_ssize_t  index  =  FT_ATOMIC_LOAD_SSIZE_RELAXED (lz -> index );
1203+ 
1204+     if  (index  <  0 ) {
12031205        item  =  PyIter_Next (lz -> it );
12041206        if  (item  !=  NULL ) {
12051207            if  (PyList_Append (lz -> saved , item )) {
@@ -1211,14 +1213,19 @@ cycle_next(PyObject *op)
12111213        /* Note:  StopIteration is already cleared by PyIter_Next() */ 
12121214        if  (PyErr_Occurred ())
12131215            return  NULL ;
1216+         index  =  0 ;
1217+         FT_ATOMIC_STORE_SSIZE_RELAXED (lz -> index , 0 );
1218+ #ifndef  Py_GIL_DISABLED 
12141219        Py_CLEAR (lz -> it );
1220+ #endif 
12151221    }
12161222    if  (PyList_GET_SIZE (lz -> saved ) ==  0 )
12171223        return  NULL ;
1218-     item  =  PyList_GET_ITEM (lz -> saved , lz -> index );
1219-     lz -> index ++ ;
1220-     if  (lz -> index  >= PyList_GET_SIZE (lz -> saved ))
1221-         lz -> index  =  0 ;
1224+     item  =  PyList_GET_ITEM (lz -> saved , index );
1225+     index ++ ;
1226+     if  (index  >= PyList_GET_SIZE (lz -> saved )) {
1227+         FT_ATOMIC_STORE_SSIZE_RELAXED (lz -> index , 0 );
1228+     }
12221229    return  Py_NewRef (item );
12231230}
12241231
 
 
   
 
     
   
   
          
    
    
     
    
      
     
     
    You can’t perform that action at this time.
  
 
    
  
    
      
        
     
       
      
     
   
 
    
    
  
 
  
 
     
    
0 commit comments