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