blob: ffd5244426ecf50560c42ef6098a389f2e27a195 [file] [log] [blame]
Brett Cannon66865d22008-03-13 20:27:00 +00001import os
2import unittest
Guido van Rossumb26a1b41998-05-20 17:05:52 +00003import random
Brett Cannon66865d22008-03-13 20:27:00 +00004from test import test_support
Guido van Rossumcc544171994-04-14 20:28:41 +00005import thread
6import time
7
Guido van Rossumcc544171994-04-14 20:28:41 +00008
Brett Cannon66865d22008-03-13 20:27:00 +00009NUMTASKS = 10
10NUMTRIPS = 3
Guido van Rossumd3b68421994-05-23 12:17:36 +000011
Guido van Rossumcc544171994-04-14 20:28:41 +000012
Jeffrey Yasskina1458532008-03-18 04:56:06 +000013_print_mutex = thread.allocate_lock()
14
Brett Cannon66865d22008-03-13 20:27:00 +000015def verbose_print(arg):
16 """Helper function for printing out debugging output."""
17 if test_support.verbose:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000018 with _print_mutex:
19 print arg
Guido van Rossumcc544171994-04-14 20:28:41 +000020
Guido van Rossumcc544171994-04-14 20:28:41 +000021
Brett Cannon66865d22008-03-13 20:27:00 +000022class BasicThreadTest(unittest.TestCase):
Guido van Rossumd3b68421994-05-23 12:17:36 +000023
Brett Cannon66865d22008-03-13 20:27:00 +000024 def setUp(self):
25 self.done_mutex = thread.allocate_lock()
26 self.done_mutex.acquire()
27 self.running_mutex = thread.allocate_lock()
28 self.random_mutex = thread.allocate_lock()
29 self.running = 0
30 self.next_ident = 0
31
32
33class ThreadRunningTests(BasicThreadTest):
34
35 def newtask(self):
36 with self.running_mutex:
37 self.next_ident += 1
38 verbose_print("creating task %s" % self.next_ident)
39 thread.start_new_thread(self.task, (self.next_ident,))
40 self.running += 1
41
42 def task(self, ident):
43 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000044 delay = random.random() / 10000.0
45 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +000046 time.sleep(delay)
47 verbose_print("task %s done" % ident)
48 with self.running_mutex:
49 self.running -= 1
50 if self.running == 0:
51 self.done_mutex.release()
52
53 def test_starting_threads(self):
54 # Basic test for thread creation.
55 for i in range(NUMTASKS):
56 self.newtask()
57 verbose_print("waiting for tasks to complete...")
58 self.done_mutex.acquire()
59 verbose_print("all tasks done")
60
61 def test_stack_size(self):
62 # Various stack size tests.
63 self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0")
64
65 thread.stack_size(0)
66 self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default")
67
68 if os.name not in ("nt", "os2", "posix"):
69 return
70
71 tss_supported = True
72 try:
73 thread.stack_size(4096)
74 except ValueError:
75 verbose_print("caught expected ValueError setting "
76 "stack_size(4096)")
77 except thread.error:
78 tss_supported = False
79 verbose_print("platform does not support changing thread stack "
80 "size")
81
82 if tss_supported:
83 fail_msg = "stack_size(%d) failed - should succeed"
84 for tss in (262144, 0x100000, 0):
85 thread.stack_size(tss)
86 self.assertEquals(thread.stack_size(), tss, fail_msg % tss)
87 verbose_print("successfully set stack_size(%d)" % tss)
88
89 for tss in (262144, 0x100000):
90 verbose_print("trying stack_size = (%d)" % tss)
91 self.next_ident = 0
92 for i in range(NUMTASKS):
93 self.newtask()
94
95 verbose_print("waiting for all tasks to complete")
96 self.done_mutex.acquire()
97 verbose_print("all tasks done")
98
99 thread.stack_size(0)
100
101
102class Barrier:
103 def __init__(self, num_threads):
104 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000105 self.waiting = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000106 self.checkin_mutex = thread.allocate_lock()
107 self.checkout_mutex = thread.allocate_lock()
108 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000109
Fred Drake004d5e62000-10-23 17:22:08 +0000110 def enter(self):
Brett Cannon66865d22008-03-13 20:27:00 +0000111 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000112 self.waiting = self.waiting + 1
Brett Cannon66865d22008-03-13 20:27:00 +0000113 if self.waiting == self.num_threads:
114 self.waiting = self.num_threads - 1
115 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000116 return
Brett Cannon66865d22008-03-13 20:27:00 +0000117 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000118
Brett Cannon66865d22008-03-13 20:27:00 +0000119 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000120 self.waiting = self.waiting - 1
121 if self.waiting == 0:
Brett Cannon66865d22008-03-13 20:27:00 +0000122 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000123 return
Brett Cannon66865d22008-03-13 20:27:00 +0000124 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000125
Guido van Rossumd3b68421994-05-23 12:17:36 +0000126
Brett Cannon66865d22008-03-13 20:27:00 +0000127class BarrierTest(BasicThreadTest):
Andrew MacIntyre92913322006-06-13 15:04:24 +0000128
Brett Cannon66865d22008-03-13 20:27:00 +0000129 def test_barrier(self):
130 self.bar = Barrier(NUMTASKS)
131 self.running = NUMTASKS
132 for i in range(NUMTASKS):
133 thread.start_new_thread(self.task2, (i,))
134 verbose_print("waiting for tasks to end")
135 self.done_mutex.acquire()
136 verbose_print("tasks done")
Andrew MacIntyre92913322006-06-13 15:04:24 +0000137
Brett Cannon66865d22008-03-13 20:27:00 +0000138 def task2(self, ident):
139 for i in range(NUMTRIPS):
140 if ident == 0:
141 # give it a good chance to enter the next
142 # barrier before the others are all out
143 # of the current one
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000144 delay = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000145 else:
146 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000147 delay = random.random() / 10000.0
148 verbose_print("task %s will run for %sus" %
149 (ident, round(delay * 1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +0000150 time.sleep(delay)
151 verbose_print("task %s entering %s" % (ident, i))
152 self.bar.enter()
153 verbose_print("task %s leaving barrier" % ident)
154 with self.running_mutex:
155 self.running -= 1
156 # Must release mutex before releasing done, else the main thread can
157 # exit and set mutex to None as part of global teardown; then
158 # mutex.release() raises AttributeError.
159 finished = self.running == 0
160 if finished:
161 self.done_mutex.release()
Andrew MacIntyre92913322006-06-13 15:04:24 +0000162
Andrew MacIntyre92913322006-06-13 15:04:24 +0000163
Brett Cannon66865d22008-03-13 20:27:00 +0000164def test_main():
165 test_support.run_unittest(ThreadRunningTests, BarrierTest)
Andrew MacIntyre92913322006-06-13 15:04:24 +0000166
Brett Cannon66865d22008-03-13 20:27:00 +0000167if __name__ == "__main__":
168 test_main()