blob: c89c5a147e20e58c270eb6203281956ad8a5b4ce [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 Heimesdd15f6c2008-03-16 00:07:10 +000012def verbose_print(arg):
13 """Helper function for printing out debugging output."""
14 if test_support.verbose:
15 print(arg)
Guido van Rossumcc544171994-04-14 20:28:41 +000016
Christian Heimesdd15f6c2008-03-16 00:07:10 +000017class BasicThreadTest(unittest.TestCase):
Guido van Rossumcc544171994-04-14 20:28:41 +000018
Christian Heimesdd15f6c2008-03-16 00:07:10 +000019 def setUp(self):
20 self.done_mutex = thread.allocate_lock()
21 self.done_mutex.acquire()
22 self.running_mutex = thread.allocate_lock()
23 self.random_mutex = thread.allocate_lock()
24 self.running = 0
25 self.next_ident = 0
Guido van Rossumcc544171994-04-14 20:28:41 +000026
Guido van Rossumd3b68421994-05-23 12:17:36 +000027
Christian Heimesdd15f6c2008-03-16 00:07:10 +000028class ThreadRunningTests(BasicThreadTest):
29
30 def newtask(self):
31 with self.running_mutex:
32 self.next_ident += 1
33 verbose_print("creating task %s" % self.next_ident)
34 thread.start_new_thread(self.task, (self.next_ident,))
35 self.running += 1
36
37 def task(self, ident):
38 with self.random_mutex:
39 delay = random.random() * NUMTASKS
40 verbose_print("task %s will run for %s" % (ident, round(delay, 1)))
41 time.sleep(delay)
42 verbose_print("task %s done" % ident)
43 with self.running_mutex:
44 self.running -= 1
45 if self.running == 0:
46 self.done_mutex.release()
47
48 def test_starting_threads(self):
49 # Basic test for thread creation.
50 for i in range(NUMTASKS):
51 self.newtask()
52 verbose_print("waiting for tasks to complete...")
53 self.done_mutex.acquire()
54 verbose_print("all tasks done")
55
56 def test_stack_size(self):
57 # Various stack size tests.
58 self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0")
59
60 thread.stack_size(0)
61 self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default")
62
63 if os.name not in ("nt", "os2", "posix"):
64 return
65
66 tss_supported = True
67 try:
68 thread.stack_size(4096)
69 except ValueError:
70 verbose_print("caught expected ValueError setting "
71 "stack_size(4096)")
72 except thread.error:
73 tss_supported = False
74 verbose_print("platform does not support changing thread stack "
75 "size")
76
77 if tss_supported:
78 fail_msg = "stack_size(%d) failed - should succeed"
79 for tss in (262144, 0x100000, 0):
80 thread.stack_size(tss)
81 self.assertEquals(thread.stack_size(), tss, fail_msg % tss)
82 verbose_print("successfully set stack_size(%d)" % tss)
83
84 for tss in (262144, 0x100000):
85 verbose_print("trying stack_size = (%d)" % tss)
86 self.next_ident = 0
87 for i in range(NUMTASKS):
88 self.newtask()
89
90 verbose_print("waiting for all tasks to complete")
91 self.done_mutex.acquire()
92 verbose_print("all tasks done")
93
94 thread.stack_size(0)
95
96
97class Barrier:
98 def __init__(self, num_threads):
99 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000100 self.waiting = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000101 self.checkin_mutex = thread.allocate_lock()
102 self.checkout_mutex = thread.allocate_lock()
103 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000104
Fred Drake004d5e62000-10-23 17:22:08 +0000105 def enter(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000106 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000107 self.waiting = self.waiting + 1
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000108 if self.waiting == self.num_threads:
109 self.waiting = self.num_threads - 1
110 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000111 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000112 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000113
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000114 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000115 self.waiting = self.waiting - 1
116 if self.waiting == 0:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000117 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000118 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000119 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000120
Guido van Rossumd3b68421994-05-23 12:17:36 +0000121
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000122class BarrierTest(BasicThreadTest):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000123
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000124 def test_barrier(self):
125 self.bar = Barrier(NUMTASKS)
126 self.running = NUMTASKS
127 for i in range(NUMTASKS):
128 thread.start_new_thread(self.task2, (i,))
129 verbose_print("waiting for tasks to end")
130 self.done_mutex.acquire()
131 verbose_print("tasks done")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000132
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000133 def task2(self, ident):
134 for i in range(NUMTRIPS):
135 if ident == 0:
136 # give it a good chance to enter the next
137 # barrier before the others are all out
138 # of the current one
139 delay = 0.001
140 else:
141 with self.random_mutex:
142 delay = random.random() * NUMTASKS
143 verbose_print("task %s will run for %s" % (ident, round(delay, 1)))
144 time.sleep(delay)
145 verbose_print("task %s entering %s" % (ident, i))
146 self.bar.enter()
147 verbose_print("task %s leaving barrier" % ident)
148 with self.running_mutex:
149 self.running -= 1
150 # Must release mutex before releasing done, else the main thread can
151 # exit and set mutex to None as part of global teardown; then
152 # mutex.release() raises AttributeError.
153 finished = self.running == 0
154 if finished:
155 self.done_mutex.release()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000156
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000157def test_main():
158 test_support.run_unittest(ThreadRunningTests, BarrierTest)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000159
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000160if __name__ == "__main__":
161 test_main()