1 | // Copyright (C) 2007 Anthony Williams |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #define BOOST_THREAD_VERSION 2 |
7 | #define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_all test suite |
8 | #include <boost/thread/detail/config.hpp> |
9 | |
10 | #include <boost/thread/thread_only.hpp> |
11 | |
12 | #include <boost/test/unit_test.hpp> |
13 | |
14 | #include "./util.inl" |
15 | #include "./condition_test_common.hpp" |
16 | |
17 | unsigned const number_of_test_threads=5; |
18 | |
19 | void do_test_condition_notify_all_wakes_from_wait() |
20 | { |
21 | wait_for_flag data; |
22 | |
23 | boost::thread_group group; |
24 | |
25 | try |
26 | { |
27 | for(unsigned i=0;i<number_of_test_threads;++i) |
28 | { |
29 | group.create_thread(threadfunc: bind(func: &wait_for_flag::wait_without_predicate, param&: data)); |
30 | } |
31 | |
32 | { |
33 | boost::unique_lock<boost::mutex> lock(data.mutex); |
34 | data.flag=true; |
35 | data.cond_var.notify_all(); |
36 | } |
37 | |
38 | group.join_all(); |
39 | BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); |
40 | } |
41 | catch(...) |
42 | { |
43 | group.join_all(); |
44 | throw; |
45 | } |
46 | } |
47 | |
48 | void do_test_condition_notify_all_wakes_from_wait_with_predicate() |
49 | { |
50 | wait_for_flag data; |
51 | |
52 | boost::thread_group group; |
53 | |
54 | try |
55 | { |
56 | for(unsigned i=0;i<number_of_test_threads;++i) |
57 | { |
58 | group.create_thread(threadfunc: bind(func: &wait_for_flag::wait_with_predicate, param&: data)); |
59 | } |
60 | |
61 | { |
62 | boost::unique_lock<boost::mutex> lock(data.mutex); |
63 | data.flag=true; |
64 | data.cond_var.notify_all(); |
65 | } |
66 | |
67 | group.join_all(); |
68 | BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); |
69 | } |
70 | catch(...) |
71 | { |
72 | group.join_all(); |
73 | throw; |
74 | } |
75 | } |
76 | |
77 | void do_test_condition_notify_all_wakes_from_timed_wait() |
78 | { |
79 | wait_for_flag data; |
80 | |
81 | boost::thread_group group; |
82 | |
83 | try |
84 | { |
85 | for(unsigned i=0;i<number_of_test_threads;++i) |
86 | { |
87 | group.create_thread(threadfunc: bind(func: &wait_for_flag::timed_wait_without_predicate, param&: data)); |
88 | } |
89 | |
90 | { |
91 | boost::unique_lock<boost::mutex> lock(data.mutex); |
92 | data.flag=true; |
93 | data.cond_var.notify_all(); |
94 | } |
95 | |
96 | group.join_all(); |
97 | BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); |
98 | } |
99 | catch(...) |
100 | { |
101 | group.join_all(); |
102 | throw; |
103 | } |
104 | } |
105 | |
106 | void do_test_condition_notify_all_wakes_from_timed_wait_with_predicate() |
107 | { |
108 | wait_for_flag data; |
109 | |
110 | boost::thread_group group; |
111 | |
112 | try |
113 | { |
114 | for(unsigned i=0;i<number_of_test_threads;++i) |
115 | { |
116 | group.create_thread(threadfunc: bind(func: &wait_for_flag::timed_wait_with_predicate, param&: data)); |
117 | } |
118 | |
119 | { |
120 | boost::unique_lock<boost::mutex> lock(data.mutex); |
121 | data.flag=true; |
122 | data.cond_var.notify_all(); |
123 | } |
124 | |
125 | group.join_all(); |
126 | BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); |
127 | } |
128 | catch(...) |
129 | { |
130 | group.join_all(); |
131 | throw; |
132 | } |
133 | } |
134 | |
135 | void do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate() |
136 | { |
137 | wait_for_flag data; |
138 | |
139 | boost::thread_group group; |
140 | |
141 | try |
142 | { |
143 | for(unsigned i=0;i<number_of_test_threads;++i) |
144 | { |
145 | group.create_thread(threadfunc: bind(func: &wait_for_flag::relative_timed_wait_with_predicate, param&: data)); |
146 | } |
147 | |
148 | { |
149 | boost::unique_lock<boost::mutex> lock(data.mutex); |
150 | data.flag=true; |
151 | data.cond_var.notify_all(); |
152 | } |
153 | |
154 | group.join_all(); |
155 | BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); |
156 | } |
157 | catch(...) |
158 | { |
159 | group.join_all(); |
160 | throw; |
161 | } |
162 | } |
163 | |
164 | namespace |
165 | { |
166 | boost::mutex multiple_wake_mutex; |
167 | boost::condition_variable multiple_wake_cond; |
168 | unsigned multiple_wake_count=0; |
169 | |
170 | void wait_for_condvar_and_increase_count() |
171 | { |
172 | boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); |
173 | multiple_wake_cond.wait(m&: lk); |
174 | ++multiple_wake_count; |
175 | } |
176 | |
177 | } |
178 | |
179 | |
180 | void do_test_notify_all_following_notify_one_wakes_all_threads() |
181 | { |
182 | boost::thread thread1(&wait_for_condvar_and_increase_count); |
183 | boost::thread thread2(&wait_for_condvar_and_increase_count); |
184 | |
185 | boost::this_thread::sleep(rel_time: boost::posix_time::milliseconds(200)); |
186 | multiple_wake_cond.notify_one(); |
187 | |
188 | boost::thread thread3(&wait_for_condvar_and_increase_count); |
189 | |
190 | boost::this_thread::sleep(rel_time: boost::posix_time::milliseconds(200)); |
191 | multiple_wake_cond.notify_one(); |
192 | multiple_wake_cond.notify_all(); |
193 | boost::this_thread::sleep(rel_time: boost::posix_time::milliseconds(200)); |
194 | |
195 | { |
196 | boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); |
197 | BOOST_CHECK(multiple_wake_count==3); |
198 | } |
199 | |
200 | thread1.join(); |
201 | thread2.join(); |
202 | thread3.join(); |
203 | } |
204 | |
205 | BOOST_AUTO_TEST_CASE(test_condition_notify_all) |
206 | { |
207 | timed_test(func: &do_test_condition_notify_all_wakes_from_wait, secs: timeout_seconds); |
208 | timed_test(func: &do_test_condition_notify_all_wakes_from_wait_with_predicate, secs: timeout_seconds); |
209 | timed_test(func: &do_test_condition_notify_all_wakes_from_timed_wait, secs: timeout_seconds); |
210 | timed_test(func: &do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, secs: timeout_seconds); |
211 | timed_test(func: &do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, secs: timeout_seconds); |
212 | timed_test(func: &do_test_notify_all_following_notify_one_wakes_all_threads, secs: timeout_seconds); |
213 | } |
214 | |
215 | |
216 | |
217 | |