blob: c4c21fed00f312e3149dde069dafda62e15ad1a4 [file] [log] [blame]
Guido van Rossumcc544171994-04-14 20:28:41 +00001# Very rudimentary test of thread module
2
3# Create a bunch of threads, let each do some work, wait until all are done
4
Barry Warsaw04f357c2002-07-23 19:04:11 +00005from test.test_support import verbose
Guido van Rossumb26a1b41998-05-20 17:05:52 +00006import random
Guido van Rossumcc544171994-04-14 20:28:41 +00007import thread
8import time
9
10mutex = thread.allocate_lock()
Guido van Rossumb26a1b41998-05-20 17:05:52 +000011rmutex = thread.allocate_lock() # for calls to random
Guido van Rossumcc544171994-04-14 20:28:41 +000012running = 0
13done = thread.allocate_lock()
14done.acquire()
15
Guido van Rossumd3b68421994-05-23 12:17:36 +000016numtasks = 10
17
Guido van Rossumcc544171994-04-14 20:28:41 +000018def task(ident):
Fred Drake004d5e62000-10-23 17:22:08 +000019 global running
20 rmutex.acquire()
21 delay = random.random() * numtasks
22 rmutex.release()
23 if verbose:
24 print 'task', ident, 'will run for', round(delay, 1), 'sec'
25 time.sleep(delay)
26 if verbose:
27 print 'task', ident, 'done'
28 mutex.acquire()
29 running = running - 1
30 if running == 0:
31 done.release()
32 mutex.release()
Guido van Rossumcc544171994-04-14 20:28:41 +000033
34next_ident = 0
35def newtask():
Fred Drake004d5e62000-10-23 17:22:08 +000036 global next_ident, running
37 mutex.acquire()
38 next_ident = next_ident + 1
39 if verbose:
40 print 'creating task', next_ident
41 thread.start_new_thread(task, (next_ident,))
42 running = running + 1
43 mutex.release()
Guido van Rossumcc544171994-04-14 20:28:41 +000044
Guido van Rossumd3b68421994-05-23 12:17:36 +000045for i in range(numtasks):
Fred Drake004d5e62000-10-23 17:22:08 +000046 newtask()
Guido van Rossumcc544171994-04-14 20:28:41 +000047
48print 'waiting for all tasks to complete'
49done.acquire()
50print 'all tasks done'
Guido van Rossumd3b68421994-05-23 12:17:36 +000051
52class barrier:
Fred Drake004d5e62000-10-23 17:22:08 +000053 def __init__(self, n):
54 self.n = n
55 self.waiting = 0
56 self.checkin = thread.allocate_lock()
57 self.checkout = thread.allocate_lock()
58 self.checkout.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +000059
Fred Drake004d5e62000-10-23 17:22:08 +000060 def enter(self):
61 checkin, checkout = self.checkin, self.checkout
Guido van Rossumd3b68421994-05-23 12:17:36 +000062
Fred Drake004d5e62000-10-23 17:22:08 +000063 checkin.acquire()
64 self.waiting = self.waiting + 1
65 if self.waiting == self.n:
66 self.waiting = self.n - 1
67 checkout.release()
68 return
69 checkin.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +000070
Fred Drake004d5e62000-10-23 17:22:08 +000071 checkout.acquire()
72 self.waiting = self.waiting - 1
73 if self.waiting == 0:
74 checkin.release()
75 return
76 checkout.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +000077
78numtrips = 3
79def task2(ident):
Fred Drake004d5e62000-10-23 17:22:08 +000080 global running
81 for i in range(numtrips):
82 if ident == 0:
83 # give it a good chance to enter the next
84 # barrier before the others are all out
85 # of the current one
86 delay = 0.001
87 else:
88 rmutex.acquire()
89 delay = random.random() * numtasks
90 rmutex.release()
91 if verbose:
92 print 'task', ident, 'will run for', round(delay, 1), 'sec'
93 time.sleep(delay)
94 if verbose:
95 print 'task', ident, 'entering barrier', i
96 bar.enter()
97 if verbose:
98 print 'task', ident, 'leaving barrier', i
99 mutex.acquire()
Tim Peters20882dd2002-02-16 07:26:27 +0000100 running -= 1
101 # Must release mutex before releasing done, else the main thread can
102 # exit and set mutex to None as part of global teardown; then
103 # mutex.release() raises AttributeError.
104 finished = running == 0
Fred Drake004d5e62000-10-23 17:22:08 +0000105 mutex.release()
Tim Peters20882dd2002-02-16 07:26:27 +0000106 if finished:
107 done.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000108
109print '\n*** Barrier Test ***'
110if done.acquire(0):
Fred Drake004d5e62000-10-23 17:22:08 +0000111 raise ValueError, "'done' should have remained acquired"
Guido van Rossumd3b68421994-05-23 12:17:36 +0000112bar = barrier(numtasks)
113running = numtasks
114for i in range(numtasks):
Fred Drake004d5e62000-10-23 17:22:08 +0000115 thread.start_new_thread(task2, (i,))
Guido van Rossumd3b68421994-05-23 12:17:36 +0000116done.acquire()
117print 'all tasks done'
Andrew MacIntyre92913322006-06-13 15:04:24 +0000118
119# not all platforms support changing thread stack size
120print '\n*** Changing thread stack size ***'
121if thread.stack_size() != 0:
122 raise ValueError, "initial stack_size not 0"
123
Tim Petersef7fe5f2006-06-13 18:37:07 +0000124thread.stack_size(0)
Andrew MacIntyre92913322006-06-13 15:04:24 +0000125if thread.stack_size() != 0:
126 raise ValueError, "stack_size not reset to default"
127
128from os import name as os_name
129if os_name in ("nt", "os2", "posix"):
130
131 tss_supported = 1
132 try:
133 thread.stack_size(4096)
134 except ValueError:
135 print 'caught expected ValueError setting stack_size(4096)'
Andrew MacIntyrea7090df2006-06-13 17:14:36 +0000136 except thread.error:
Andrew MacIntyre92913322006-06-13 15:04:24 +0000137 tss_supported = 0
138 print 'platform does not support changing thread stack size'
139
140 if tss_supported:
141 failed = lambda s, e: s != e
142 fail_msg = "stack_size(%d) failed - should succeed"
Andrew MacIntyre93e3ecb2006-06-13 19:02:35 +0000143 for tss in (262144, 0x100000, 0):
Andrew MacIntyre92913322006-06-13 15:04:24 +0000144 thread.stack_size(tss)
145 if failed(thread.stack_size(), tss):
146 raise ValueError, fail_msg % tss
147 print 'successfully set stack_size(%d)' % tss
148
Andrew MacIntyre93e3ecb2006-06-13 19:02:35 +0000149 for tss in (262144, 0x100000):
Andrew MacIntyre92913322006-06-13 15:04:24 +0000150 print 'trying stack_size = %d' % tss
151 next_ident = 0
152 for i in range(numtasks):
153 newtask()
154
155 print 'waiting for all tasks to complete'
156 done.acquire()
157 print 'all tasks done'
158
159 # reset stack size to default
160 thread.stack_size(0)