mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 3d4ac1a2c2
			
		
	
	
		3d4ac1a2c2
		
			
		
	
	
	
	
		
			
			Concurrent accesses from multiple threads to the same `cell` object did not scale well in the free-threaded build. Use `_PyStackRef` and optimistically avoid locking to improve scaling. With the locks around cell reads gone, some of the free threading tests were prone to starvation: the readers were able to run in a tight loop and the writer threads weren't scheduled frequently enough to make timely progress. Adjust the tests to avoid this. Co-authored-by: Donghee Na <donghee.na@python.org>
		
			
				
	
	
		
			96 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import unittest
 | |
| 
 | |
| from threading import Thread, Barrier
 | |
| from unittest import TestCase
 | |
| 
 | |
| from test.support import threading_helper
 | |
| 
 | |
| 
 | |
| NTHREAD = 10
 | |
| OBJECT_COUNT = 5_000
 | |
| 
 | |
| 
 | |
| class C:
 | |
|     def __init__(self, v):
 | |
|         self.v = v
 | |
| 
 | |
| 
 | |
| @threading_helper.requires_working_threading()
 | |
| class TestList(TestCase):
 | |
|     def test_racing_iter_append(self):
 | |
|         l = []
 | |
| 
 | |
|         barrier = Barrier(NTHREAD + 1)
 | |
|         def writer_func(l):
 | |
|             barrier.wait()
 | |
|             for i in range(OBJECT_COUNT):
 | |
|                 l.append(C(i + OBJECT_COUNT))
 | |
| 
 | |
|         def reader_func(l):
 | |
|             barrier.wait()
 | |
|             while True:
 | |
|                 count = len(l)
 | |
|                 for i, x in enumerate(l):
 | |
|                     self.assertEqual(x.v, i + OBJECT_COUNT)
 | |
|                 if count == OBJECT_COUNT:
 | |
|                     break
 | |
| 
 | |
|         writer = Thread(target=writer_func, args=(l,))
 | |
|         readers = []
 | |
|         for x in range(NTHREAD):
 | |
|             reader = Thread(target=reader_func, args=(l,))
 | |
|             readers.append(reader)
 | |
|             reader.start()
 | |
| 
 | |
|         writer.start()
 | |
|         writer.join()
 | |
|         for reader in readers:
 | |
|             reader.join()
 | |
| 
 | |
|     def test_racing_iter_extend(self):
 | |
|         l = []
 | |
| 
 | |
|         barrier = Barrier(NTHREAD + 1)
 | |
|         def writer_func():
 | |
|             barrier.wait()
 | |
|             for i in range(OBJECT_COUNT):
 | |
|                 l.extend([C(i + OBJECT_COUNT)])
 | |
| 
 | |
|         def reader_func():
 | |
|             barrier.wait()
 | |
|             while True:
 | |
|                 count = len(l)
 | |
|                 for i, x in enumerate(l):
 | |
|                     self.assertEqual(x.v, i + OBJECT_COUNT)
 | |
|                 if count == OBJECT_COUNT:
 | |
|                     break
 | |
| 
 | |
|         writer = Thread(target=writer_func)
 | |
|         readers = []
 | |
|         for x in range(NTHREAD):
 | |
|             reader = Thread(target=reader_func)
 | |
|             readers.append(reader)
 | |
|             reader.start()
 | |
| 
 | |
|         writer.start()
 | |
|         writer.join()
 | |
|         for reader in readers:
 | |
|             reader.join()
 | |
| 
 | |
|     def test_store_list_int(self):
 | |
|         def copy_back_and_forth(b, l):
 | |
|             b.wait()
 | |
|             for _ in range(100):
 | |
|                 l[0] = l[1]
 | |
|                 l[1] = l[0]
 | |
| 
 | |
|         l = [0, 1]
 | |
|         barrier = Barrier(NTHREAD)
 | |
|         threads = [Thread(target=copy_back_and_forth, args=(barrier, l))
 | |
|                    for _ in range(NTHREAD)]
 | |
|         with threading_helper.start_threads(threads):
 | |
|             pass
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     unittest.main()
 |