1// Copyright (C) 2001-2003
2// William E. Kempf
3// Copyright (C) 2007 Anthony Williams
4//
5// Distributed under the Boost Software License, Version 1.0. (See accompanying
6// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8#define BOOST_THREAD_VERSION 2
9#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
10#define BOOST_TEST_MODULE Boost.Threads: condition test suite
11#include <boost/thread/detail/config.hpp>
12
13#include <boost/thread/condition.hpp>
14#include <boost/thread/thread_only.hpp>
15#include <boost/thread/xtime.hpp>
16
17#include <boost/config.hpp>
18#include <boost/test/unit_test.hpp>
19
20#include "./util.inl"
21
22struct condition_test_data
23{
24 condition_test_data() : notified(0), awoken(0) { }
25
26 boost::mutex mutex;
27 boost::condition_variable condition;
28 int notified;
29 int awoken;
30};
31
32void condition_test_thread(condition_test_data* data)
33{
34 boost::unique_lock<boost::mutex> lock(data->mutex);
35 BOOST_CHECK(lock ? true : false);
36 while (!(data->notified > 0))
37 data->condition.wait(m&: lock);
38 BOOST_CHECK(lock ? true : false);
39 data->awoken++;
40}
41
42struct cond_predicate
43{
44 cond_predicate(int& var, int val) : _var(var), _val(val) { }
45#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
46 cond_predicate(cond_predicate const&) = default;
47#endif
48
49 bool operator()() { return _var == _val; }
50
51 int& _var;
52 int _val;
53
54private:
55 void operator=(cond_predicate&);
56};
57
58void condition_test_waits(condition_test_data* data)
59{
60 boost::unique_lock<boost::mutex> lock(data->mutex);
61 BOOST_CHECK(lock ? true : false);
62
63 // Test wait.
64 while (data->notified != 1)
65 data->condition.wait(m&: lock);
66 BOOST_CHECK(lock ? true : false);
67 BOOST_CHECK_EQUAL(data->notified, 1);
68 data->awoken++;
69 data->condition.notify_one();
70
71 // Test predicate wait.
72 data->condition.wait(m&: lock, pred: cond_predicate(data->notified, 2));
73 BOOST_CHECK(lock ? true : false);
74 BOOST_CHECK_EQUAL(data->notified, 2);
75 data->awoken++;
76 data->condition.notify_one();
77
78 // Test timed_wait.
79 boost::xtime xt = delay(secs: 10);
80 while (data->notified != 3)
81 data->condition.timed_wait(m&: lock, abs_time: xt);
82 BOOST_CHECK(lock ? true : false);
83 BOOST_CHECK_EQUAL(data->notified, 3);
84 data->awoken++;
85 data->condition.notify_one();
86
87 // Test predicate timed_wait.
88 xt = delay(secs: 10);
89 cond_predicate pred(data->notified, 4);
90 BOOST_CHECK(data->condition.timed_wait(lock, xt, pred));
91 BOOST_CHECK(lock ? true : false);
92 BOOST_CHECK(pred());
93 BOOST_CHECK_EQUAL(data->notified, 4);
94 data->awoken++;
95 data->condition.notify_one();
96
97 // Test predicate timed_wait with relative timeout
98 cond_predicate pred_rel(data->notified, 5);
99 BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel));
100 BOOST_CHECK(lock ? true : false);
101 BOOST_CHECK(pred_rel());
102 BOOST_CHECK_EQUAL(data->notified, 5);
103 data->awoken++;
104 data->condition.notify_one();
105}
106
107void do_test_condition_waits()
108{
109 condition_test_data data;
110
111 boost::thread thread(bind(func: &condition_test_waits, param: &data));
112
113 {
114 boost::unique_lock<boost::mutex> lock(data.mutex);
115 BOOST_CHECK(lock ? true : false);
116
117 boost::thread::sleep(xt: delay(secs: 1));
118 data.notified++;
119 data.condition.notify_one();
120 while (data.awoken != 1)
121 data.condition.wait(m&: lock);
122 BOOST_CHECK(lock ? true : false);
123 BOOST_CHECK_EQUAL(data.awoken, 1);
124
125 boost::thread::sleep(xt: delay(secs: 1));
126 data.notified++;
127 data.condition.notify_one();
128 while (data.awoken != 2)
129 data.condition.wait(m&: lock);
130 BOOST_CHECK(lock ? true : false);
131 BOOST_CHECK_EQUAL(data.awoken, 2);
132
133 boost::thread::sleep(xt: delay(secs: 1));
134 data.notified++;
135 data.condition.notify_one();
136 while (data.awoken != 3)
137 data.condition.wait(m&: lock);
138 BOOST_CHECK(lock ? true : false);
139 BOOST_CHECK_EQUAL(data.awoken, 3);
140
141 boost::thread::sleep(xt: delay(secs: 1));
142 data.notified++;
143 data.condition.notify_one();
144 while (data.awoken != 4)
145 data.condition.wait(m&: lock);
146 BOOST_CHECK(lock ? true : false);
147 BOOST_CHECK_EQUAL(data.awoken, 4);
148
149
150 boost::thread::sleep(xt: delay(secs: 1));
151 data.notified++;
152 data.condition.notify_one();
153 while (data.awoken != 5)
154 data.condition.wait(m&: lock);
155 BOOST_CHECK(lock ? true : false);
156 BOOST_CHECK_EQUAL(data.awoken, 5);
157 }
158
159 thread.join();
160 BOOST_CHECK_EQUAL(data.awoken, 5);
161}
162
163BOOST_AUTO_TEST_CASE(test_condition_waits)
164{
165 // We should have already tested notify_one here, so
166 // a timed test with the default execution_monitor::use_condition
167 // should be OK, and gives the fastest performance
168 timed_test(func: &do_test_condition_waits, secs: 12);
169}
170
171void do_test_condition_wait_is_a_interruption_point()
172{
173 condition_test_data data;
174
175 boost::thread thread(bind(func: &condition_test_thread, param: &data));
176
177 thread.interrupt();
178 thread.join();
179 BOOST_CHECK_EQUAL(data.awoken,0);
180}
181
182
183BOOST_AUTO_TEST_CASE(test_condition_wait_is_a_interruption_point)
184{
185 timed_test(func: &do_test_condition_wait_is_a_interruption_point, secs: 1);
186}
187
188

source code of boost/libs/thread/test/test_condition.cpp