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