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