]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (C) 2001-2003 |
2 | // William E. Kempf | |
3 | // Copyright (C) 2008 Anthony Williams | |
4 | // | |
5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #define BOOST_THREAD_VERSION 2 | |
9 | #define BOOST_THREAD_PROVIDES_INTERRUPTIONS | |
10 | ||
11 | #include <boost/thread/detail/config.hpp> | |
12 | ||
13 | #include <boost/thread/thread_only.hpp> | |
14 | #include <boost/thread/xtime.hpp> | |
f67539c2 | 15 | #include <boost/bind/bind.hpp> |
7c673cae FG |
16 | #include <boost/ref.hpp> |
17 | #include <boost/utility.hpp> | |
18 | ||
19 | #define BOOST_TEST_MODULE Boost.Threads: thread test suite | |
20 | ||
21 | #include <boost/test/unit_test.hpp> | |
22 | ||
23 | #define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only | |
24 | #include "./util.inl" | |
25 | ||
26 | int test_value; | |
27 | ||
28 | void simple_thread() | |
29 | { | |
30 | test_value = 999; | |
31 | } | |
32 | ||
33 | void comparison_thread(boost::thread::id parent) | |
34 | { | |
35 | boost::thread::id const my_id=boost::this_thread::get_id(); | |
36 | ||
37 | BOOST_CHECK(my_id != parent); | |
38 | boost::thread::id const my_id2=boost::this_thread::get_id(); | |
39 | BOOST_CHECK(my_id == my_id2); | |
40 | ||
41 | boost::thread::id const no_thread_id=boost::thread::id(); | |
42 | BOOST_CHECK(my_id != no_thread_id); | |
43 | } | |
44 | ||
45 | BOOST_AUTO_TEST_CASE(test_sleep) | |
46 | { | |
47 | boost::xtime xt = delay(3); | |
48 | boost::thread::sleep(xt); | |
49 | ||
50 | // Ensure it's in a range instead of checking actual equality due to time | |
51 | // lapse | |
52 | BOOST_CHECK(boost::threads::test::in_range(xt, 2)); | |
53 | } | |
54 | ||
55 | void do_test_creation() | |
56 | { | |
57 | test_value = 0; | |
58 | boost::thread thrd(&simple_thread); | |
59 | thrd.join(); | |
60 | BOOST_CHECK_EQUAL(test_value, 999); | |
61 | } | |
62 | ||
63 | BOOST_AUTO_TEST_CASE(test_creation) | |
64 | { | |
65 | timed_test(&do_test_creation, 1); | |
66 | } | |
67 | ||
68 | void do_test_id_comparison() | |
69 | { | |
70 | boost::thread::id const self=boost::this_thread::get_id(); | |
71 | boost::thread thrd(boost::bind(&comparison_thread, self)); | |
72 | thrd.join(); | |
73 | } | |
74 | ||
75 | BOOST_AUTO_TEST_CASE(test_id_comparison) | |
76 | { | |
77 | timed_test(&do_test_id_comparison, 1); | |
78 | } | |
79 | ||
80 | void interruption_point_thread(boost::mutex* m,bool* failed) | |
81 | { | |
82 | boost::unique_lock<boost::mutex> lk(*m); | |
83 | boost::this_thread::interruption_point(); | |
84 | *failed=true; | |
85 | } | |
86 | ||
87 | void do_test_thread_interrupts_at_interruption_point() | |
88 | { | |
89 | boost::mutex m; | |
90 | bool failed=false; | |
91 | boost::unique_lock<boost::mutex> lk(m); | |
92 | boost::thread thrd(boost::bind(&interruption_point_thread,&m,&failed)); | |
93 | thrd.interrupt(); | |
94 | lk.unlock(); | |
95 | thrd.join(); | |
96 | BOOST_CHECK(!failed); | |
97 | } | |
98 | ||
99 | BOOST_AUTO_TEST_CASE(test_thread_interrupts_at_interruption_point) | |
100 | { | |
101 | timed_test(&do_test_thread_interrupts_at_interruption_point, 1); | |
102 | } | |
103 | ||
104 | void disabled_interruption_point_thread(boost::mutex* m,bool* failed) | |
105 | { | |
106 | boost::unique_lock<boost::mutex> lk(*m); | |
107 | boost::this_thread::disable_interruption dc; | |
108 | boost::this_thread::interruption_point(); | |
109 | *failed=false; | |
110 | } | |
111 | ||
112 | void do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point() | |
113 | { | |
114 | boost::mutex m; | |
115 | bool failed=true; | |
116 | boost::unique_lock<boost::mutex> lk(m); | |
117 | boost::thread thrd(boost::bind(&disabled_interruption_point_thread,&m,&failed)); | |
118 | thrd.interrupt(); | |
119 | lk.unlock(); | |
120 | thrd.join(); | |
121 | BOOST_CHECK(!failed); | |
122 | } | |
123 | ||
124 | BOOST_AUTO_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point) | |
125 | { | |
126 | timed_test(&do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point, 1); | |
127 | } | |
128 | ||
129 | struct non_copyable_functor: | |
130 | boost::noncopyable | |
131 | { | |
132 | unsigned value; | |
133 | ||
134 | non_copyable_functor(): boost::noncopyable(), | |
135 | value(0) | |
136 | {} | |
137 | ||
138 | void operator()() | |
139 | { | |
140 | value=999; | |
141 | } | |
142 | }; | |
143 | ||
144 | void do_test_creation_through_reference_wrapper() | |
145 | { | |
146 | non_copyable_functor f; | |
147 | ||
148 | boost::thread thrd(boost::ref(f)); | |
149 | thrd.join(); | |
150 | BOOST_CHECK_EQUAL(f.value, 999u); | |
151 | } | |
152 | ||
153 | BOOST_AUTO_TEST_CASE(test_creation_through_reference_wrapper) | |
154 | { | |
155 | timed_test(&do_test_creation_through_reference_wrapper, 1); | |
156 | } | |
157 | ||
158 | struct long_running_thread | |
159 | { | |
160 | boost::condition_variable cond; | |
161 | boost::mutex mut; | |
162 | bool done; | |
163 | ||
164 | long_running_thread(): | |
165 | done(false) | |
166 | {} | |
167 | ||
168 | void operator()() | |
169 | { | |
170 | boost::unique_lock<boost::mutex> lk(mut); | |
171 | while(!done) | |
172 | { | |
173 | cond.wait(lk); | |
174 | } | |
175 | } | |
176 | }; | |
177 | ||
178 | void do_test_timed_join() | |
179 | { | |
180 | long_running_thread f; | |
181 | boost::thread thrd(boost::ref(f)); | |
182 | BOOST_CHECK(thrd.joinable()); | |
183 | boost::system_time xt=delay(3); | |
184 | bool const joined=thrd.timed_join(xt); | |
185 | BOOST_CHECK(boost::threads::test::in_range(boost::get_xtime(xt), 2)); | |
186 | BOOST_CHECK(!joined); | |
187 | BOOST_CHECK(thrd.joinable()); | |
188 | { | |
189 | boost::unique_lock<boost::mutex> lk(f.mut); | |
190 | f.done=true; | |
191 | f.cond.notify_one(); | |
192 | } | |
193 | ||
194 | xt=delay(3); | |
195 | bool const joined2=thrd.timed_join(xt); | |
196 | boost::system_time const now=boost::get_system_time(); | |
197 | BOOST_CHECK(xt>now); | |
198 | BOOST_CHECK(joined2); | |
199 | BOOST_CHECK(!thrd.joinable()); | |
200 | } | |
201 | ||
202 | BOOST_AUTO_TEST_CASE(test_timed_join) | |
203 | { | |
204 | timed_test(&do_test_timed_join, 10); | |
205 | } | |
206 | ||
207 | BOOST_AUTO_TEST_CASE(test_swap) | |
208 | { | |
92f5a8d4 TL |
209 | boost::thread t(&simple_thread); |
210 | boost::thread t2(&simple_thread); | |
7c673cae FG |
211 | boost::thread::id id1=t.get_id(); |
212 | boost::thread::id id2=t2.get_id(); | |
213 | ||
214 | t.swap(t2); | |
215 | BOOST_CHECK(t.get_id()==id2); | |
216 | BOOST_CHECK(t2.get_id()==id1); | |
217 | ||
218 | swap(t,t2); | |
219 | BOOST_CHECK(t.get_id()==id1); | |
220 | BOOST_CHECK(t2.get_id()==id2); | |
221 | } | |
222 |