• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
15 #include <boost/bind/bind.hpp>
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 
simple_thread()28 void simple_thread()
29 {
30     test_value = 999;
31 }
32 
comparison_thread(boost::thread::id parent)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 
BOOST_AUTO_TEST_CASE(test_sleep)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 
do_test_creation()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 
BOOST_AUTO_TEST_CASE(test_creation)63 BOOST_AUTO_TEST_CASE(test_creation)
64 {
65     timed_test(&do_test_creation, 1);
66 }
67 
do_test_id_comparison()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 
BOOST_AUTO_TEST_CASE(test_id_comparison)75 BOOST_AUTO_TEST_CASE(test_id_comparison)
76 {
77     timed_test(&do_test_id_comparison, 1);
78 }
79 
interruption_point_thread(boost::mutex * m,bool * failed)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 
do_test_thread_interrupts_at_interruption_point()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 
BOOST_AUTO_TEST_CASE(test_thread_interrupts_at_interruption_point)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 
disabled_interruption_point_thread(boost::mutex * m,bool * failed)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 
do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point()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 
BOOST_AUTO_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point)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 
non_copyable_functornon_copyable_functor134     non_copyable_functor(): boost::noncopyable(),
135         value(0)
136     {}
137 
operator ()non_copyable_functor138     void operator()()
139     {
140         value=999;
141     }
142 };
143 
do_test_creation_through_reference_wrapper()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 
BOOST_AUTO_TEST_CASE(test_creation_through_reference_wrapper)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 
long_running_threadlong_running_thread164     long_running_thread():
165         done(false)
166     {}
167 
operator ()long_running_thread168     void operator()()
169     {
170         boost::unique_lock<boost::mutex> lk(mut);
171         while(!done)
172         {
173             cond.wait(lk);
174         }
175     }
176 };
177 
do_test_timed_join()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 
BOOST_AUTO_TEST_CASE(test_timed_join)202 BOOST_AUTO_TEST_CASE(test_timed_join)
203 {
204     timed_test(&do_test_timed_join, 10);
205 }
206 
BOOST_AUTO_TEST_CASE(test_swap)207 BOOST_AUTO_TEST_CASE(test_swap)
208 {
209     boost::thread t(&simple_thread);
210     boost::thread t2(&simple_thread);
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 
223