blob: 01d66552957b4976940cc83d857e3378e643c37f [file] [log] [blame]
Christian Heimesdd15f6c2008-03-16 00:07:10 +00001import os
2import unittest
Guido van Rossumb26a1b41998-05-20 17:05:52 +00003import random
Christian Heimesdd15f6c2008-03-16 00:07:10 +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
Christian Heimesdd15f6c2008-03-16 00:07:10 +00009NUMTASKS = 10
10NUMTRIPS = 3
Guido van Rossumd3b68421994-05-23 12:17:36 +000011
Christian Heimesb186d002008-03-18 15:15:01 +000012_print_mutex = thread.allocate_lock()
13
Christian Heimesdd15f6c2008-03-16 00:07:10 +000014def verbose_print(arg):
15 """Helper function for printing out debugging output."""
16 if test_support.verbose:
Christian Heimesb186d002008-03-18 15:15:01 +000017 with _print_mutex:
18 print(arg)
Guido van Rossumcc544171994-04-14 20:28:41 +000019
Christian Heimesdd15f6c2008-03-16 00:07:10 +000020class BasicThreadTest(unittest.TestCase):
Guido van Rossumcc544171994-04-14 20:28:41 +000021
Christian Heimesdd15f6c2008-03-16 00:07:10 +000022 def setUp(self):
23 self.done_mutex = thread.allocate_lock()
24 self.done_mutex.acquire()
25 self.running_mutex = thread.allocate_lock()
26 self.random_mutex = thread.allocate_lock()
27 self.running = 0
28 self.next_ident = 0
Guido van Rossumcc544171994-04-14 20:28:41 +000029
Guido van Rossumd3b68421994-05-23 12:17:36 +000030
Christian Heimesdd15f6c2008-03-16 00:07:10 +000031class ThreadRunningTests(BasicThreadTest):
32
33 def newtask(self):
34 with self.running_mutex:
35 self.next_ident += 1
36 verbose_print("creating task %s" % self.next_ident)
37 thread.start_new_thread(self.task, (self.next_ident,))
38 self.running += 1
39
40 def task(self, ident):
41 with self.random_mutex:
Christian Heimesb186d002008-03-18 15:15:01 +000042 delay = random.random() / 10000.0
43 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Christian Heimesdd15f6c2008-03-16 00:07:10 +000044 time.sleep(delay)
45 verbose_print("task %s done" % ident)
46 with self.running_mutex:
47 self.running -= 1
48 if self.running == 0:
49 self.done_mutex.release()
50
51 def test_starting_threads(self):
52 # Basic test for thread creation.
53 for i in range(NUMTASKS):
54 self.newtask()
55 verbose_print("waiting for tasks to complete...")
56 self.done_mutex.acquire()
57 verbose_print("all tasks done")
58
59 def test_stack_size(self):
60 # Various stack size tests.
61 self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0")
62
63 thread.stack_size(0)
64 self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default")
65
66 if os.name not in ("nt", "os2", "posix"):
67 return
68
69 tss_supported = True
70 try:
71 thread.stack_size(4096)
72 except ValueError:
73 verbose_print("caught expected ValueError setting "
74 "stack_size(4096)")
75 except thread.error:
76 tss_supported = False
77 verbose_print("platform does not support changing thread stack "
78 "size")
79
80 if tss_supported:
81 fail_msg = "stack_size(%d) failed - should succeed"
82 for tss in (262144, 0x100000, 0):
83 thread.stack_size(tss)
84 self.assertEquals(thread.stack_size(), tss, fail_msg % tss)
85 verbose_print("successfully set stack_size(%d)" % tss)
86
87 for tss in (262144, 0x100000):
88 verbose_print("trying stack_size = (%d)" % tss)
89 self.next_ident = 0
90 for i in range(NUMTASKS):
91 self.newtask()
92
93 verbose_print("waiting for all tasks to complete")
94 self.done_mutex.acquire()
95 verbose_print("all tasks done")
96
97 thread.stack_size(0)
98
99
100class Barrier:
101 def __init__(self, num_threads):
102 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000103 self.waiting = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000104 self.checkin_mutex = thread.allocate_lock()
105 self.checkout_mutex = thread.allocate_lock()
106 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000107
Fred Drake004d5e62000-10-23 17:22:08 +0000108 def enter(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000109 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000110 self.waiting = self.waiting + 1
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000111 if self.waiting == self.num_threads:
112 self.waiting = self.num_threads - 1
113 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000114 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000115 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000116
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000117 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000118 self.waiting = self.waiting - 1
119 if self.waiting == 0:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000120 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000121 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000122 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000123
Guido van Rossumd3b68421994-05-23 12:17:36 +0000124
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000125class BarrierTest(BasicThreadTest):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000126
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000127 def test_barrier(self):
128 self.bar = Barrier(NUMTASKS)
129 self.running = NUMTASKS
130 for i in range(NUMTASKS):
131 thread.start_new_thread(self.task2, (i,))
132 verbose_print("waiting for tasks to end")
133 self.done_mutex.acquire()
134 verbose_print("tasks done")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000135
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000136 def task2(self, ident):
137 for i in range(NUMTRIPS):
138 if ident == 0:
139 # give it a good chance to enter the next
140 # barrier before the others are all out
141 # of the current one
Christian Heimesb186d002008-03-18 15:15:01 +0000142 delay = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000143 else:
144 with self.random_mutex:
Christian Heimesb186d002008-03-18 15:15:01 +0000145 delay = random.random() / 10000.0
146 verbose_print("task %s will run for %sus" %
147 (ident, round(delay * 1e6)))
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000148 time.sleep(delay)
149 verbose_print("task %s entering %s" % (ident, i))
150 self.bar.enter()
151 verbose_print("task %s leaving barrier" % ident)
152 with self.running_mutex:
153 self.running -= 1
154 # Must release mutex before releasing done, else the main thread can
155 # exit and set mutex to None as part of global teardown; then
156 # mutex.release() raises AttributeError.
157 finished = self.running == 0
158 if finished:
159 self.done_mutex.release()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000160
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000161def test_main():
162 test_support.run_unittest(ThreadRunningTests, BarrierTest)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000163
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000164if __name__ == "__main__":
165 test_main()