2 // Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // This test is based on the tests of Boost.Thread
17 #include <boost/test/unit_test.hpp>
19 #include <boost/fiber/all.hpp>
21 typedef std::chrono::nanoseconds ns
;
22 typedef std::chrono::milliseconds ms
;
27 std::chrono::system_clock::time_point
delay(int secs
, int msecs
=0, int /*nsecs*/=0) {
28 std::chrono::system_clock::time_point t
= std::chrono::system_clock::now();
29 t
+= std::chrono::seconds( secs
);
30 t
+= std::chrono::milliseconds( msecs
);
31 //t += std::chrono::nanoseconds( nsecs);
36 struct condition_test_data
{
37 condition_test_data() : notified(0), awoken(0) { }
39 boost::fibers::mutex mutex
;
40 boost::fibers::condition_variable_any cond
;
45 void condition_test_fiber(condition_test_data
* data
) {
48 while (!(data
->notified
> 0))
49 data
->cond
.wait(data
->mutex
);
56 struct cond_predicate
{
57 cond_predicate(int& var
, int val
) : _var(var
), _val(val
) { }
59 bool operator()() { return _var
== _val
; }
64 void operator=(cond_predicate
&);
68 void notify_one_fn( boost::fibers::condition_variable_any
& cond
) {
72 void notify_all_fn( boost::fibers::condition_variable_any
& cond
) {
77 boost::fibers::mutex
& mtx
,
78 boost::fibers::condition_variable_any
& cond
) {
85 void test_one_waiter_notify_one() {
87 boost::fibers::mutex mtx
;
88 boost::fibers::condition_variable_any cond
;
90 boost::fibers::fiber
f1(
91 boost::fibers::launch::post
,
95 BOOST_CHECK_EQUAL( 0, value1
);
97 boost::fibers::fiber
f2(
98 boost::fibers::launch::post
,
102 BOOST_CHECK_EQUAL( 0, value1
);
107 BOOST_CHECK_EQUAL( 1, value1
);
110 void test_two_waiter_notify_one() {
112 boost::fibers::mutex mtx
;
113 boost::fibers::condition_variable_any cond
;
115 boost::fibers::fiber
f1(
116 boost::fibers::launch::post
,
120 BOOST_CHECK_EQUAL( 0, value1
);
122 boost::fibers::fiber
f2(
123 boost::fibers::launch::post
,
127 BOOST_CHECK_EQUAL( 0, value1
);
129 boost::fibers::fiber
f3(
130 boost::fibers::launch::post
,
133 BOOST_CHECK_EQUAL( 0, value1
);
135 boost::fibers::fiber
f4(
136 boost::fibers::launch::post
,
139 BOOST_CHECK_EQUAL( 0, value1
);
146 BOOST_CHECK_EQUAL( 2, value1
);
149 void test_two_waiter_notify_all() {
151 boost::fibers::mutex mtx
;
152 boost::fibers::condition_variable_any cond
;
154 boost::fibers::fiber
f1(
155 boost::fibers::launch::post
,
159 BOOST_CHECK_EQUAL( 0, value1
);
161 boost::fibers::fiber
f2(
162 boost::fibers::launch::post
,
166 BOOST_CHECK_EQUAL( 0, value1
);
168 boost::fibers::fiber
f3(
169 boost::fibers::launch::post
,
172 BOOST_CHECK_EQUAL( 0, value1
);
174 boost::fibers::fiber
f4(
175 boost::fibers::launch::post
,
179 BOOST_CHECK_EQUAL( 0, value1
);
181 boost::fibers::fiber
f5(
182 boost::fibers::launch::post
,
185 BOOST_CHECK_EQUAL( 0, value1
);
193 BOOST_CHECK_EQUAL( 3, value1
);
201 void fn1( boost::fibers::mutex
& m
, boost::fibers::condition_variable_any
& cv
) {
203 BOOST_CHECK(test2
== 0);
209 BOOST_CHECK(test2
!= 0);
213 void fn2( boost::fibers::mutex
& m
, boost::fibers::condition_variable_any
& cv
) {
215 BOOST_CHECK(test2
== 0);
218 std::chrono::system_clock::time_point t0
= std::chrono::system_clock::now();
219 std::chrono::system_clock::time_point t
= t0
+ ms(250);
221 while (test2
== 0 && cv
.wait_until(m
, t
) == boost::fibers::cv_status::no_timeout
)
223 std::chrono::system_clock::time_point t1
= std::chrono::system_clock::now();
225 BOOST_CHECK(t1
- t0
< ms(250));
226 BOOST_CHECK(test2
!= 0);
228 BOOST_CHECK(t1
- t0
- ms(250) < ms(count
*250+100+1000));
229 BOOST_CHECK(test2
== 0);
239 explicit Pred(int& i
) :
247 void fn3( boost::fibers::mutex
& m
, boost::fibers::condition_variable_any
& cv
) {
249 BOOST_CHECK(test2
== 0);
252 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
253 std::chrono::steady_clock::time_point t
= t0
+ ms(250);
254 bool r
= cv
.wait_until(m
, t
, Pred(test2
));
255 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
257 BOOST_CHECK(t1
- t0
< ms(250));
258 BOOST_CHECK(test2
!= 0);
261 BOOST_CHECK(t1
- t0
- ms(250) < ms(250+100));
262 BOOST_CHECK(test2
== 0);
269 void fn4( boost::fibers::mutex
& m
, boost::fibers::condition_variable_any
& cv
) {
271 BOOST_CHECK(test2
== 0);
274 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
276 while (test2
== 0 && cv
.wait_for(m
, ms(250)) == boost::fibers::cv_status::no_timeout
)
278 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
280 BOOST_CHECK(t1
- t0
< ms(250));
281 BOOST_CHECK(test2
!= 0);
283 BOOST_CHECK(t1
- t0
- ms(250) < ms(count
*250+100+1000));
284 BOOST_CHECK(test2
== 0);
290 void fn5( boost::fibers::mutex
& m
, boost::fibers::condition_variable_any
& cv
) {
292 BOOST_CHECK(test2
== 0);
295 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
297 cv
.wait_for(m
, ms(250), Pred(test2
));
299 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
301 BOOST_CHECK(t1
- t0
< ms(250+1000));
302 BOOST_CHECK(test2
!= 0);
304 BOOST_CHECK(t1
- t0
- ms(250) < ms(count
*250+100));
305 BOOST_CHECK(test2
== 0);
311 void do_test_condition_wait() {
316 boost::fibers::mutex m
;
317 boost::fibers::condition_variable_any cv
;
319 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn1
, std::ref( m
), std::ref( cv
) );
320 BOOST_CHECK(test1
== 0);
323 BOOST_CHECK(test1
!= 0);
330 void test_condition_wait() {
331 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_condition_wait
).join();
332 do_test_condition_wait();
335 void do_test_condition_wait_until() {
340 boost::fibers::mutex m
;
341 boost::fibers::condition_variable_any cv
;
344 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn2
, std::ref( m
), std::ref( cv
) );
345 BOOST_CHECK(test1
== 0);
348 BOOST_CHECK(test1
!= 0);
358 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn2
, std::ref( m
), std::ref( cv
) );
359 BOOST_CHECK(test1
== 0);
362 BOOST_CHECK(test1
!= 0);
368 void test_condition_wait_until() {
369 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_condition_wait_until
).join();
370 do_test_condition_wait_until();
373 void do_test_condition_wait_until_pred() {
378 boost::fibers::mutex m
;
379 boost::fibers::condition_variable_any cv
;
382 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn3
, std::ref( m
), std::ref( cv
) );
383 BOOST_CHECK(test1
== 0);
386 BOOST_CHECK(test1
!= 0);
396 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn3
, std::ref( m
), std::ref( cv
) );
397 BOOST_CHECK(test1
== 0);
400 BOOST_CHECK(test1
!= 0);
406 void test_condition_wait_until_pred() {
407 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_condition_wait_until_pred
).join();
408 do_test_condition_wait_until_pred();
411 void do_test_condition_wait_for() {
416 boost::fibers::mutex m
;
417 boost::fibers::condition_variable_any cv
;
420 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn4
, std::ref( m
), std::ref( cv
) );
421 BOOST_CHECK(test1
== 0);
424 BOOST_CHECK(test1
!= 0);
434 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn4
, std::ref( m
), std::ref( cv
) );
435 BOOST_CHECK(test1
== 0);
438 BOOST_CHECK(test1
!= 0);
444 void test_condition_wait_for() {
445 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_condition_wait_for
).join();
446 do_test_condition_wait_for();
449 void do_test_condition_wait_for_pred() {
454 boost::fibers::mutex m
;
455 boost::fibers::condition_variable_any cv
;
458 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn5
, std::ref( m
), std::ref( cv
) );
459 BOOST_CHECK(test1
== 0);
462 BOOST_CHECK(test1
!= 0);
472 boost::fibers::fiber
f( boost::fibers::launch::post
, & fn5
, std::ref( m
), std::ref( cv
) );
473 BOOST_CHECK(test1
== 0);
476 BOOST_CHECK(test1
!= 0);
482 void test_condition_wait_for_pred() {
483 boost::fibers::fiber( boost::fibers::launch::post
, & do_test_condition_wait_for_pred
).join();
484 do_test_condition_wait_for_pred();
487 boost::unit_test::test_suite
* init_unit_test_suite( int, char* []) {
488 boost::unit_test::test_suite
* test
=
489 BOOST_TEST_SUITE("Boost.Fiber: condition_variable_any test suite");
491 test
->add( BOOST_TEST_CASE( & test_one_waiter_notify_one
) );
492 test
->add( BOOST_TEST_CASE( & test_two_waiter_notify_one
) );
493 test
->add( BOOST_TEST_CASE( & test_two_waiter_notify_all
) );
494 test
->add( BOOST_TEST_CASE( & test_condition_wait
) );
495 test
->add( BOOST_TEST_CASE( & test_condition_wait_until
) );
496 test
->add( BOOST_TEST_CASE( & test_condition_wait_until_pred
) );
497 test
->add( BOOST_TEST_CASE( & test_condition_wait_for
) );
498 test
->add( BOOST_TEST_CASE( & test_condition_wait_for_pred
) );