| # Very rudimentary test of thread module | 
 |  | 
 | # Create a bunch of threads, let each do some work, wait until all are done | 
 |  | 
 | from test.test_support import verbose | 
 | import random | 
 | import thread | 
 | import time | 
 |  | 
 | mutex = thread.allocate_lock() | 
 | rmutex = thread.allocate_lock() # for calls to random | 
 | running = 0 | 
 | done = thread.allocate_lock() | 
 | done.acquire() | 
 |  | 
 | numtasks = 10 | 
 |  | 
 | def task(ident): | 
 |     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() | 
 |  | 
 | next_ident = 0 | 
 | def newtask(): | 
 |     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() | 
 |  | 
 | for i in range(numtasks): | 
 |     newtask() | 
 |  | 
 | print 'waiting for all tasks to complete' | 
 | done.acquire() | 
 | print 'all tasks done' | 
 |  | 
 | class barrier: | 
 |     def __init__(self, n): | 
 |         self.n = n | 
 |         self.waiting = 0 | 
 |         self.checkin  = thread.allocate_lock() | 
 |         self.checkout = thread.allocate_lock() | 
 |         self.checkout.acquire() | 
 |  | 
 |     def enter(self): | 
 |         checkin, checkout = self.checkin, self.checkout | 
 |  | 
 |         checkin.acquire() | 
 |         self.waiting = self.waiting + 1 | 
 |         if self.waiting == self.n: | 
 |             self.waiting = self.n - 1 | 
 |             checkout.release() | 
 |             return | 
 |         checkin.release() | 
 |  | 
 |         checkout.acquire() | 
 |         self.waiting = self.waiting - 1 | 
 |         if self.waiting == 0: | 
 |             checkin.release() | 
 |             return | 
 |         checkout.release() | 
 |  | 
 | numtrips = 3 | 
 | def task2(ident): | 
 |     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() | 
 |     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 | 
 |     mutex.release() | 
 |     if finished: | 
 |         done.release() | 
 |  | 
 | print '\n*** Barrier Test ***' | 
 | if done.acquire(0): | 
 |     raise ValueError, "'done' should have remained acquired" | 
 | bar = barrier(numtasks) | 
 | running = numtasks | 
 | for i in range(numtasks): | 
 |     thread.start_new_thread(task2, (i,)) | 
 | done.acquire() | 
 | print 'all tasks done' | 
 |  | 
 | # 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.error: | 
 |         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 (262144, 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 (262144, 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) |