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 
8 #define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_one test suite
9 
10 #include <boost/thread/detail/config.hpp>
11 
12 #include <boost/thread/thread_only.hpp>
13 
14 #include <boost/test/unit_test.hpp>
15 
16 #include "./util.inl"
17 #include "./condition_test_common.hpp"
18 
do_test_condition_notify_one_wakes_from_wait()19 void do_test_condition_notify_one_wakes_from_wait()
20 {
21     wait_for_flag data;
22 
23     boost::thread thread(bind(&wait_for_flag::wait_without_predicate, data));
24 
25     {
26         boost::unique_lock<boost::mutex> lock(data.mutex);
27         data.flag=true;
28         data.cond_var.notify_one();
29     }
30 
31     thread.join();
32     BOOST_CHECK(data.woken);
33 }
34 
do_test_condition_notify_one_wakes_from_wait_with_predicate()35 void do_test_condition_notify_one_wakes_from_wait_with_predicate()
36 {
37     wait_for_flag data;
38 
39     boost::thread thread(bind(&wait_for_flag::wait_with_predicate, data));
40 
41     {
42         boost::unique_lock<boost::mutex> lock(data.mutex);
43         data.flag=true;
44         data.cond_var.notify_one();
45     }
46 
47     thread.join();
48     BOOST_CHECK(data.woken);
49 }
50 
do_test_condition_notify_one_wakes_from_timed_wait()51 void do_test_condition_notify_one_wakes_from_timed_wait()
52 {
53     wait_for_flag data;
54 
55     boost::thread thread(bind(&wait_for_flag::timed_wait_without_predicate, data));
56 
57     {
58         boost::unique_lock<boost::mutex> lock(data.mutex);
59         data.flag=true;
60         data.cond_var.notify_one();
61     }
62 
63     thread.join();
64     BOOST_CHECK(data.woken);
65 }
66 
do_test_condition_notify_one_wakes_from_timed_wait_with_predicate()67 void do_test_condition_notify_one_wakes_from_timed_wait_with_predicate()
68 {
69     wait_for_flag data;
70 
71     boost::thread thread(bind(&wait_for_flag::timed_wait_with_predicate, data));
72 
73     {
74         boost::unique_lock<boost::mutex> lock(data.mutex);
75         data.flag=true;
76         data.cond_var.notify_one();
77     }
78 
79     thread.join();
80     BOOST_CHECK(data.woken);
81 }
82 
do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate()83 void do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate()
84 {
85     wait_for_flag data;
86 
87     boost::thread thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data));
88 
89     {
90         boost::unique_lock<boost::mutex> lock(data.mutex);
91         data.flag=true;
92         data.cond_var.notify_one();
93     }
94 
95     thread.join();
96     BOOST_CHECK(data.woken);
97 }
98 
99 namespace
100 {
101     boost::mutex multiple_wake_mutex;
102     boost::condition_variable multiple_wake_cond;
103     unsigned multiple_wake_count=0;
104 
wait_for_condvar_and_increase_count()105     void wait_for_condvar_and_increase_count()
106     {
107         boost::unique_lock<boost::mutex> lk(multiple_wake_mutex);
108         multiple_wake_cond.wait(lk);
109         ++multiple_wake_count;
110     }
111 
112 }
113 
114 
do_test_multiple_notify_one_calls_wakes_multiple_threads()115 void do_test_multiple_notify_one_calls_wakes_multiple_threads()
116 {
117     boost::thread thread1(&wait_for_condvar_and_increase_count);
118     boost::thread thread2(&wait_for_condvar_and_increase_count);
119 
120     boost::this_thread::sleep(boost::posix_time::milliseconds(200));
121     multiple_wake_cond.notify_one();
122 
123     boost::thread thread3(&wait_for_condvar_and_increase_count);
124 
125     boost::this_thread::sleep(boost::posix_time::milliseconds(200));
126     multiple_wake_cond.notify_one();
127     multiple_wake_cond.notify_one();
128     boost::this_thread::sleep(boost::posix_time::milliseconds(200));
129 
130     {
131         boost::unique_lock<boost::mutex> lk(multiple_wake_mutex);
132         BOOST_CHECK(multiple_wake_count==3);
133     }
134 
135     thread1.join();
136     thread2.join();
137     thread3.join();
138 }
139 
BOOST_AUTO_TEST_CASE(test_condition_notify_one)140 BOOST_AUTO_TEST_CASE(test_condition_notify_one)
141 {
142     timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
143     timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
144     timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex);
145     timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
146     timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
147     timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
148 }
149