blob: 73d87b8cf3e304fc480eaf94822d4b54a0248067 [file] [log] [blame]
Christian Heimesdd15f6c2008-03-16 00:07:10 +00001import os
2import unittest
Guido van Rossumb26a1b41998-05-20 17:05:52 +00003import random
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Georg Brandl2067bfd2008-05-25 13:05:15 +00005import _thread as thread
Guido van Rossumcc544171994-04-14 20:28:41 +00006import 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."""
Benjamin Petersonee8712c2008-05-20 21:35:26 +000016 if 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()
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000027 self.created = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +000028 self.running = 0
29 self.next_ident = 0
Guido van Rossumcc544171994-04-14 20:28:41 +000030
Guido van Rossumd3b68421994-05-23 12:17:36 +000031
Christian Heimesdd15f6c2008-03-16 00:07:10 +000032class ThreadRunningTests(BasicThreadTest):
33
34 def newtask(self):
35 with self.running_mutex:
36 self.next_ident += 1
37 verbose_print("creating task %s" % self.next_ident)
38 thread.start_new_thread(self.task, (self.next_ident,))
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000039 self.created += 1
Christian Heimesdd15f6c2008-03-16 00:07:10 +000040 self.running += 1
41
42 def task(self, ident):
43 with self.random_mutex:
Christian Heimesb186d002008-03-18 15:15:01 +000044 delay = random.random() / 10000.0
45 verbose_print("task %s will run for %sus" % (ident, round(delay*1e6)))
Christian Heimesdd15f6c2008-03-16 00:07:10 +000046 time.sleep(delay)
47 verbose_print("task %s done" % ident)
48 with self.running_mutex:
49 self.running -= 1
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000050 if self.created == NUMTASKS and self.running == 0:
Christian Heimesdd15f6c2008-03-16 00:07:10 +000051 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
Antoine Pitrou1ff7f2c2009-10-23 18:35:18 +000092 self.created = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +000093 for i in range(NUMTASKS):
94 self.newtask()
95
96 verbose_print("waiting for all tasks to complete")
97 self.done_mutex.acquire()
98 verbose_print("all tasks done")
99
100 thread.stack_size(0)
101
102
103class Barrier:
104 def __init__(self, num_threads):
105 self.num_threads = num_threads
Fred Drake004d5e62000-10-23 17:22:08 +0000106 self.waiting = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000107 self.checkin_mutex = thread.allocate_lock()
108 self.checkout_mutex = thread.allocate_lock()
109 self.checkout_mutex.acquire()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000110
Fred Drake004d5e62000-10-23 17:22:08 +0000111 def enter(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000112 self.checkin_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000113 self.waiting = self.waiting + 1
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000114 if self.waiting == self.num_threads:
115 self.waiting = self.num_threads - 1
116 self.checkout_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000117 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000118 self.checkin_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000119
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000120 self.checkout_mutex.acquire()
Fred Drake004d5e62000-10-23 17:22:08 +0000121 self.waiting = self.waiting - 1
122 if self.waiting == 0:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000123 self.checkin_mutex.release()
Fred Drake004d5e62000-10-23 17:22:08 +0000124 return
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000125 self.checkout_mutex.release()
Guido van Rossumd3b68421994-05-23 12:17:36 +0000126
Guido van Rossumd3b68421994-05-23 12:17:36 +0000127
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000128class BarrierTest(BasicThreadTest):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000129
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000130 def test_barrier(self):
131 self.bar = Barrier(NUMTASKS)
132 self.running = NUMTASKS
133 for i in range(NUMTASKS):
134 thread.start_new_thread(self.task2, (i,))
135 verbose_print("waiting for tasks to end")
136 self.done_mutex.acquire()
137 verbose_print("tasks done")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000138
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000139 def task2(self, ident):
140 for i in range(NUMTRIPS):
141 if ident == 0:
142 # give it a good chance to enter the next
143 # barrier before the others are all out
144 # of the current one
Christian Heimesb186d002008-03-18 15:15:01 +0000145 delay = 0
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000146 else:
147 with self.random_mutex:
Christian Heimesb186d002008-03-18 15:15:01 +0000148 delay = random.random() / 10000.0
149 verbose_print("task %s will run for %sus" %
150 (ident, round(delay * 1e6)))
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000151 time.sleep(delay)
152 verbose_print("task %s entering %s" % (ident, i))
153 self.bar.enter()
154 verbose_print("task %s leaving barrier" % ident)
155 with self.running_mutex:
156 self.running -= 1
157 # Must release mutex before releasing done, else the main thread can
158 # exit and set mutex to None as part of global teardown; then
159 # mutex.release() raises AttributeError.
160 finished = self.running == 0
161 if finished:
162 self.done_mutex.release()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000163
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000164def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000165 support.run_unittest(ThreadRunningTests, BarrierTest)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000166
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000167if __name__ == "__main__":
168 test_main()