| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | # Very rudimentary test of thread module | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Create a bunch of threads, let each do some work, wait until all are done | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-23 19:04:11 +00:00
										 |  |  | from test.test_support import verbose | 
					
						
							| 
									
										
										
										
											1998-05-20 17:05:52 +00:00
										 |  |  | import random | 
					
						
							| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | import thread | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | mutex = thread.allocate_lock() | 
					
						
							| 
									
										
										
										
											1998-05-20 17:05:52 +00:00
										 |  |  | rmutex = thread.allocate_lock() # for calls to random | 
					
						
							| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | running = 0 | 
					
						
							|  |  |  | done = thread.allocate_lock() | 
					
						
							|  |  |  | done.acquire() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | numtasks = 10 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | def task(ident): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     global running | 
					
						
							|  |  |  |     rmutex.acquire() | 
					
						
							|  |  |  |     delay = random.random() * numtasks | 
					
						
							|  |  |  |     rmutex.release() | 
					
						
							|  |  |  |     if verbose: | 
					
						
							|  |  |  |         print 'task', ident, 'will run for', round(delay, 1), 'sec' | 
					
						
							|  |  |  |     time.sleep(delay) | 
					
						
							|  |  |  |     if verbose: | 
					
						
							|  |  |  |         print 'task', ident, 'done' | 
					
						
							|  |  |  |     mutex.acquire() | 
					
						
							|  |  |  |     running = running - 1 | 
					
						
							|  |  |  |     if running == 0: | 
					
						
							|  |  |  |         done.release() | 
					
						
							|  |  |  |     mutex.release() | 
					
						
							| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | next_ident = 0 | 
					
						
							|  |  |  | def newtask(): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     global next_ident, running | 
					
						
							|  |  |  |     mutex.acquire() | 
					
						
							|  |  |  |     next_ident = next_ident + 1 | 
					
						
							|  |  |  |     if verbose: | 
					
						
							|  |  |  |         print 'creating task', next_ident | 
					
						
							|  |  |  |     thread.start_new_thread(task, (next_ident,)) | 
					
						
							|  |  |  |     running = running + 1 | 
					
						
							|  |  |  |     mutex.release() | 
					
						
							| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | for i in range(numtasks): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     newtask() | 
					
						
							| 
									
										
										
										
											1994-04-14 20:28:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | print 'waiting for all tasks to complete' | 
					
						
							|  |  |  | done.acquire() | 
					
						
							|  |  |  | print 'all tasks done' | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class barrier: | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     def __init__(self, n): | 
					
						
							|  |  |  |         self.n = n | 
					
						
							|  |  |  |         self.waiting = 0 | 
					
						
							|  |  |  |         self.checkin  = thread.allocate_lock() | 
					
						
							|  |  |  |         self.checkout = thread.allocate_lock() | 
					
						
							|  |  |  |         self.checkout.acquire() | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     def enter(self): | 
					
						
							|  |  |  |         checkin, checkout = self.checkin, self.checkout | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |         checkin.acquire() | 
					
						
							|  |  |  |         self.waiting = self.waiting + 1 | 
					
						
							|  |  |  |         if self.waiting == self.n: | 
					
						
							|  |  |  |             self.waiting = self.n - 1 | 
					
						
							|  |  |  |             checkout.release() | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         checkin.release() | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |         checkout.acquire() | 
					
						
							|  |  |  |         self.waiting = self.waiting - 1 | 
					
						
							|  |  |  |         if self.waiting == 0: | 
					
						
							|  |  |  |             checkin.release() | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         checkout.release() | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | numtrips = 3 | 
					
						
							|  |  |  | def task2(ident): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     global running | 
					
						
							|  |  |  |     for i in range(numtrips): | 
					
						
							|  |  |  |         if ident == 0: | 
					
						
							|  |  |  |             # give it a good chance to enter the next | 
					
						
							|  |  |  |             # barrier before the others are all out | 
					
						
							|  |  |  |             # of the current one | 
					
						
							|  |  |  |             delay = 0.001 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             rmutex.acquire() | 
					
						
							|  |  |  |             delay = random.random() * numtasks | 
					
						
							|  |  |  |             rmutex.release() | 
					
						
							|  |  |  |         if verbose: | 
					
						
							|  |  |  |             print 'task', ident, 'will run for', round(delay, 1), 'sec' | 
					
						
							|  |  |  |         time.sleep(delay) | 
					
						
							|  |  |  |         if verbose: | 
					
						
							|  |  |  |             print 'task', ident, 'entering barrier', i | 
					
						
							|  |  |  |         bar.enter() | 
					
						
							|  |  |  |         if verbose: | 
					
						
							|  |  |  |             print 'task', ident, 'leaving barrier', i | 
					
						
							|  |  |  |     mutex.acquire() | 
					
						
							| 
									
										
										
										
											2002-02-16 07:26:27 +00:00
										 |  |  |     running -= 1 | 
					
						
							|  |  |  |     # Must release mutex before releasing done, else the main thread can | 
					
						
							|  |  |  |     # exit and set mutex to None as part of global teardown; then | 
					
						
							|  |  |  |     # mutex.release() raises AttributeError. | 
					
						
							|  |  |  |     finished = running == 0 | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     mutex.release() | 
					
						
							| 
									
										
										
										
											2002-02-16 07:26:27 +00:00
										 |  |  |     if finished: | 
					
						
							|  |  |  |         done.release() | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | print '\n*** Barrier Test ***' | 
					
						
							|  |  |  | if done.acquire(0): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     raise ValueError, "'done' should have remained acquired" | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | bar = barrier(numtasks) | 
					
						
							|  |  |  | running = numtasks | 
					
						
							|  |  |  | for i in range(numtasks): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     thread.start_new_thread(task2, (i,)) | 
					
						
							| 
									
										
										
										
											1994-05-23 12:17:36 +00:00
										 |  |  | done.acquire() | 
					
						
							|  |  |  | print 'all tasks done' | 
					
						
							| 
									
										
										
										
											2006-06-13 15:04:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # not all platforms support changing thread stack size | 
					
						
							|  |  |  | print '\n*** Changing thread stack size ***' | 
					
						
							|  |  |  | if thread.stack_size() != 0: | 
					
						
							|  |  |  |     raise ValueError, "initial stack_size not 0" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | thread.stack_size(0)  | 
					
						
							|  |  |  | if thread.stack_size() != 0: | 
					
						
							|  |  |  |     raise ValueError, "stack_size not reset to default" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from os import name as os_name | 
					
						
							|  |  |  | if os_name in ("nt", "os2", "posix"): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tss_supported = 1 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         thread.stack_size(4096) | 
					
						
							|  |  |  |     except ValueError: | 
					
						
							|  |  |  |         print 'caught expected ValueError setting stack_size(4096)' | 
					
						
							|  |  |  |     except thread.ThreadError: | 
					
						
							|  |  |  |         tss_supported = 0 | 
					
						
							|  |  |  |         print 'platform does not support changing thread stack size' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if tss_supported: | 
					
						
							|  |  |  |         failed = lambda s, e: s != e | 
					
						
							|  |  |  |         fail_msg = "stack_size(%d) failed - should succeed" | 
					
						
							|  |  |  |         for tss in (32768, 0x100000, 0): | 
					
						
							|  |  |  |             thread.stack_size(tss) | 
					
						
							|  |  |  |             if failed(thread.stack_size(), tss): | 
					
						
							|  |  |  |                 raise ValueError, fail_msg % tss | 
					
						
							|  |  |  |             print 'successfully set stack_size(%d)' % tss | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for tss in (32768, 0x100000): | 
					
						
							|  |  |  |             print 'trying stack_size = %d' % tss | 
					
						
							|  |  |  |             next_ident = 0 | 
					
						
							|  |  |  |             for i in range(numtasks): | 
					
						
							|  |  |  |                 newtask() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             print 'waiting for all tasks to complete' | 
					
						
							|  |  |  |             done.acquire() | 
					
						
							|  |  |  |             print 'all tasks done' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # reset stack size to default | 
					
						
							|  |  |  |         thread.stack_size(0) |