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