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 
do_test_condition_notify_all_wakes_from_wait()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(bind(&wait_for_flag::wait_without_predicate, 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 
do_test_condition_notify_all_wakes_from_wait_with_predicate()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(bind(&wait_for_flag::wait_with_predicate, 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 
do_test_condition_notify_all_wakes_from_timed_wait()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(bind(&wait_for_flag::timed_wait_without_predicate, 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 
do_test_condition_notify_all_wakes_from_timed_wait_with_predicate()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(bind(&wait_for_flag::timed_wait_with_predicate, 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 
do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate()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(bind(&wait_for_flag::relative_timed_wait_with_predicate, 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 
wait_for_condvar_and_increase_count()170     void wait_for_condvar_and_increase_count()
171     {
172         boost::unique_lock<boost::mutex> lk(multiple_wake_mutex);
173         multiple_wake_cond.wait(lk);
174         ++multiple_wake_count;
175     }
176 
177 }
178 
179 
do_test_notify_all_following_notify_one_wakes_all_threads()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(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(boost::posix_time::milliseconds(200));
191     multiple_wake_cond.notify_one();
192     multiple_wake_cond.notify_all();
193     boost::this_thread::sleep(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 
BOOST_AUTO_TEST_CASE(test_condition_notify_all)205 BOOST_AUTO_TEST_CASE(test_condition_notify_all)
206 {
207     timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
208     timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds);
209     timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds);
210     timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds);
211     timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds);
212     timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds);
213 }
214 
215 
216 
217