| # 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' |