blob: 66ad22f25adb1154bd6234e991be9eff04992469 [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()
Antoine Pitroub5cf8a02009-10-23 18:32:15 +000029 self.created = 0
Brett Cannon66865d22008-03-13 20:27:00 +000030 self.running = 0
31 self.next_ident = 0
32
33
34class ThreadRunningTests(BasicThreadTest):
35
36 def newtask(self):
37 with self.running_mutex:
38 self.next_ident += 1
39 verbose_print("creating task %s" % self.next_ident)
40 thread.start_new_thread(self.task, (self.next_ident,))
Antoine Pitroub5cf8a02009-10-23 18:32:15 +000041 self.created += 1
Brett Cannon66865d22008-03-13 20:27:00 +000042 self.running += 1
43
44 def task(self, ident):
45 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +000046 delay = random.random() / 10000.0
47 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +000048 time.sleep(delay)
49 verbose_print("task %s done" % ident)
50 with self.running_mutex:
51 self.running -= 1
Antoine Pitroub5cf8a02009-10-23 18:32:15 +000052 if self.created == NUMTASKS and self.running == 0:
Brett Cannon66865d22008-03-13 20:27:00 +000053 self.done_mutex.release()
54
55 def test_starting_threads(self):
56 # Basic test for thread creation.
57 for i in range(NUMTASKS):
58 self.newtask()
59 verbose_print("waiting for tasks to complete...")
60 self.done_mutex.acquire()
61 verbose_print("all tasks done")
62
63 def test_stack_size(self):
64 # Various stack size tests.
65 self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0")
66
67 thread.stack_size(0)
68 self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default")
69
70 if os.name not in ("nt", "os2", "posix"):
71 return
72
73 tss_supported = True
74 try:
75 thread.stack_size(4096)
76 except ValueError:
77 verbose_print("caught expected ValueError setting "
78 "stack_size(4096)")
79 except thread.error:
80 tss_supported = False
81 verbose_print("platform does not support changing thread stack "
82 "size")
83
84 if tss_supported:
85 fail_msg = "stack_size(%d) failed - should succeed"
86 for tss in (262144, 0x100000, 0):
87 thread.stack_size(tss)
88 self.assertEquals(thread.stack_size(), tss, fail_msg % tss)
89 verbose_print("successfully set stack_size(%d)" % tss)
90
91 for tss in (262144, 0x100000):
92 verbose_print("trying stack_size = (%d)" % tss)
93 self.next_ident = 0
Antoine Pitroub5cf8a02009-10-23 18:32:15 +000094 self.created = 0
Brett Cannon66865d22008-03-13 20:27:00 +000095 for i in range(NUMTASKS):
96 self.newtask()
97
98 verbose_print("waiting for all tasks to complete")
99 self.done_mutex.acquire()
100 verbose_print("all tasks done")
101
102 thread.stack_size(0)
103
104
105class Barrier:
106 def __init__(self, num_threads):
107 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000108 self.waiting = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000109 self.checkin_mutex = thread.allocate_lock()
110 self.checkout_mutex = thread.allocate_lock()
111 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000112
Fred Drake004d5e62000-10-23 17:22:08 +0000113 def enter(self):
Brett Cannon66865d22008-03-13 20:27:00 +0000114 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000115 self.waiting = self.waiting + 1
Brett Cannon66865d22008-03-13 20:27:00 +0000116 if self.waiting == self.num_threads:
117 self.waiting = self.num_threads - 1
118 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000119 return
Brett Cannon66865d22008-03-13 20:27:00 +0000120 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000121
Brett Cannon66865d22008-03-13 20:27:00 +0000122 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000123 self.waiting = self.waiting - 1
124 if self.waiting == 0:
Brett Cannon66865d22008-03-13 20:27:00 +0000125 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000126 return
Brett Cannon66865d22008-03-13 20:27:00 +0000127 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000128
Guido van Rossumd3b68421994-05-23 12:17:36 +0000129
Brett Cannon66865d22008-03-13 20:27:00 +0000130class BarrierTest(BasicThreadTest):
Andrew MacIntyre92913322006-06-13 15:04:24 +0000131
Brett Cannon66865d22008-03-13 20:27:00 +0000132 def test_barrier(self):
133 self.bar = Barrier(NUMTASKS)
134 self.running = NUMTASKS
135 for i in range(NUMTASKS):
136 thread.start_new_thread(self.task2, (i,))
137 verbose_print("waiting for tasks to end")
138 self.done_mutex.acquire()
139 verbose_print("tasks done")
Andrew MacIntyre92913322006-06-13 15:04:24 +0000140
Brett Cannon66865d22008-03-13 20:27:00 +0000141 def task2(self, ident):
142 for i in range(NUMTRIPS):
143 if ident == 0:
144 # give it a good chance to enter the next
145 # barrier before the others are all out
146 # of the current one
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000147 delay = 0
Brett Cannon66865d22008-03-13 20:27:00 +0000148 else:
149 with self.random_mutex:
Jeffrey Yasskina1458532008-03-18 04:56:06 +0000150 delay = random.random() / 10000.0
151 verbose_print("task %s will run for %sus" %
152 (ident, round(delay * 1e6)))
Brett Cannon66865d22008-03-13 20:27:00 +0000153 time.sleep(delay)
154 verbose_print("task %s entering %s" % (ident, i))
155 self.bar.enter()
156 verbose_print("task %s leaving barrier" % ident)
157 with self.running_mutex:
158 self.running -= 1
159 # Must release mutex before releasing done, else the main thread can
160 # exit and set mutex to None as part of global teardown; then
161 # mutex.release() raises AttributeError.
162 finished = self.running == 0
163 if finished:
164 self.done_mutex.release()
Andrew MacIntyre92913322006-06-13 15:04:24 +0000165
Andrew MacIntyre92913322006-06-13 15:04:24 +0000166
Brett Cannon66865d22008-03-13 20:27:00 +0000167def test_main():
168 test_support.run_unittest(ThreadRunningTests, BarrierTest)
Andrew MacIntyre92913322006-06-13 15:04:24 +0000169
Brett Cannon66865d22008-03-13 20:27:00 +0000170if __name__ == "__main__":
171 test_main()