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
18 #include <boost/test/unit_test.hpp>
20 #include <boost/fiber/all.hpp>
22 typedef std::chrono::nanoseconds ns
;
23 typedef std::chrono::milliseconds ms
;
28 std::chrono::system_clock::time_point
delay(int secs
, int msecs
=0, int nsecs
=0) {
29 std::chrono::system_clock::time_point t
= std::chrono::system_clock::now();
30 t
+= std::chrono::seconds( secs
);
31 t
+= std::chrono::milliseconds( msecs
);
32 //t += std::chrono::nanoseconds( nsecs);
37 struct condition_test_data
{
38 condition_test_data() : notified(0), awoken(0) { }
40 boost::fibers::mutex mutex
;
41 boost::fibers::condition_variable cond
;
46 void condition_test_fiber(condition_test_data
* data
) {
47 std::unique_lock
<boost::fibers::mutex
> lock(data
->mutex
);
48 BOOST_CHECK(lock
? true : false);
49 while (!(data
->notified
> 0))
50 data
->cond
.wait(lock
);
51 BOOST_CHECK(lock
? true : false);
55 struct cond_predicate
{
56 cond_predicate(int& var
, int val
) : _var(var
), _val(val
) { }
58 bool operator()() { return _var
== _val
; }
63 void operator=(cond_predicate
&);
67 void notify_one_fn( boost::fibers::condition_variable
& cond
) {
71 void notify_all_fn( boost::fibers::condition_variable
& cond
) {
76 boost::fibers::mutex
& mtx
,
77 boost::fibers::condition_variable
& cond
) {
78 std::unique_lock
< boost::fibers::mutex
> lk( mtx
);
83 void test_one_waiter_notify_one() {
85 boost::fibers::mutex mtx
;
86 boost::fibers::condition_variable cond
;
88 boost::fibers::fiber
f1(
89 boost::fibers::launch::dispatch
,
93 BOOST_CHECK_EQUAL( 0, value
);
95 boost::fibers::fiber
f2(
96 boost::fibers::launch::dispatch
,
100 BOOST_CHECK_EQUAL( 0, value
);
105 BOOST_CHECK_EQUAL( 1, value
);
108 void test_two_waiter_notify_one() {
110 boost::fibers::mutex mtx
;
111 boost::fibers::condition_variable cond
;
113 boost::fibers::fiber
f1(
114 boost::fibers::launch::dispatch
,
118 BOOST_CHECK_EQUAL( 0, value
);
120 boost::fibers::fiber
f2(
121 boost::fibers::launch::dispatch
,
125 BOOST_CHECK_EQUAL( 0, value
);
127 boost::fibers::fiber
f3(
128 boost::fibers::launch::dispatch
,
131 BOOST_CHECK_EQUAL( 0, value
);
133 boost::fibers::fiber
f4(
134 boost::fibers::launch::dispatch
,
137 BOOST_CHECK_EQUAL( 1, value
);
144 BOOST_CHECK_EQUAL( 2, value
);
147 void test_two_waiter_notify_all() {
149 boost::fibers::mutex mtx
;
150 boost::fibers::condition_variable cond
;
152 boost::fibers::fiber
f1(
153 boost::fibers::launch::dispatch
,
157 BOOST_CHECK_EQUAL( 0, value
);
159 boost::fibers::fiber
f2(
160 boost::fibers::launch::dispatch
,
164 BOOST_CHECK_EQUAL( 0, value
);
166 boost::fibers::fiber
f3(
167 boost::fibers::launch::dispatch
,
170 BOOST_CHECK_EQUAL( 0, value
);
172 boost::fibers::fiber
f4(
173 boost::fibers::launch::dispatch
,
177 BOOST_CHECK_EQUAL( 2, value
);
179 boost::fibers::fiber
f5(
180 boost::fibers::launch::dispatch
,
183 BOOST_CHECK_EQUAL( 2, value
);
191 BOOST_CHECK_EQUAL( 3, value
);
199 void fn1( boost::fibers::mutex
& m
, boost::fibers::condition_variable
& cv
) {
200 std::unique_lock
< boost::fibers::mutex
> lk( m
);
201 BOOST_CHECK(test2
== 0);
207 BOOST_CHECK(test2
!= 0);
210 void fn2( boost::fibers::mutex
& m
, boost::fibers::condition_variable
& cv
) {
211 std::unique_lock
< boost::fibers::mutex
> lk( m
);
212 BOOST_CHECK(test2
== 0);
215 std::chrono::system_clock::time_point t0
= std::chrono::system_clock::now();
216 std::chrono::system_clock::time_point t
= t0
+ ms(250);
218 while (test2
== 0 && cv
.wait_until(lk
, t
) == boost::fibers::cv_status::no_timeout
)
220 std::chrono::system_clock::time_point t1
= std::chrono::system_clock::now();
222 BOOST_CHECK(t1
- t0
< ms(250));
223 BOOST_CHECK(test2
!= 0);
225 BOOST_CHECK(t1
- t0
- ms(250) < ms(count
*250+5+1000));
226 BOOST_CHECK(test2
== 0);
235 explicit Pred(int& i
) :
243 void fn3( boost::fibers::mutex
& m
, boost::fibers::condition_variable
& cv
) {
244 std::unique_lock
< boost::fibers::mutex
> lk( m
);
245 BOOST_CHECK(test2
== 0);
248 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
249 std::chrono::steady_clock::time_point t
= t0
+ ms(250);
250 bool r
= cv
.wait_until(lk
, t
, Pred(test2
));
251 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
253 BOOST_CHECK(t1
- t0
< ms(250));
254 BOOST_CHECK(test2
!= 0);
257 BOOST_CHECK(t1
- t0
- ms(250) < ms(250+2));
258 BOOST_CHECK(test2
== 0);
264 void fn4( boost::fibers::mutex
& m
, boost::fibers::condition_variable
& cv
) {
265 std::unique_lock
< boost::fibers::mutex
> lk( m
);
266 BOOST_CHECK(test2
== 0);
269 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
271 while (test2
== 0 && cv
.wait_for(lk
, ms(250)) == boost::fibers::cv_status::no_timeout
)
273 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
275 BOOST_CHECK(t1
- t0
< ms(250));
276 BOOST_CHECK(test2
!= 0);
278 BOOST_CHECK(t1
- t0
- ms(250) < ms(count
*250+5+1000));
279 BOOST_CHECK(test2
== 0);
284 void fn5( boost::fibers::mutex
& m
, boost::fibers::condition_variable
& cv
) {
285 std::unique_lock
< boost::fibers::mutex
> lk( m
);
286 BOOST_CHECK(test2
== 0);
289 std::chrono::steady_clock::time_point t0
= std::chrono::steady_clock::now();
291 cv
.wait_for(lk
, ms(250), Pred(test2
));
293 std::chrono::steady_clock::time_point t1
= std::chrono::steady_clock::now();
295 BOOST_CHECK(t1
- t0
< ms(250+1000));
296 BOOST_CHECK(test2
!= 0);
298 BOOST_CHECK(t1
- t0
- ms(250) < ms(count
*250+2));
299 BOOST_CHECK(test2
== 0);
304 void do_test_condition_wait() {
309 boost::fibers::mutex m
;
310 boost::fibers::condition_variable cv
;
311 std::unique_lock
< boost::fibers::mutex
> lk( m
);
312 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn1
, std::ref( m
), std::ref( cv
) );
313 BOOST_CHECK(test1
== 0);
316 BOOST_CHECK(test1
!= 0);
323 void test_condition_wait() {
324 boost::fibers::fiber( boost::fibers::launch::dispatch
, & do_test_condition_wait
).join();
325 do_test_condition_wait();
328 void do_test_condition_wait_until() {
333 boost::fibers::mutex m
;
334 boost::fibers::condition_variable cv
;
336 std::unique_lock
< boost::fibers::mutex
> lk( m
);
337 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn2
, std::ref( m
), std::ref( cv
) );
338 BOOST_CHECK(test1
== 0);
341 BOOST_CHECK(test1
!= 0);
350 std::unique_lock
< boost::fibers::mutex
> lk( m
);
351 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn2
, std::ref( m
), std::ref( cv
) );
352 BOOST_CHECK(test1
== 0);
355 BOOST_CHECK(test1
!= 0);
361 void test_condition_wait_until() {
362 boost::fibers::fiber( boost::fibers::launch::dispatch
, & do_test_condition_wait_until
).join();
363 do_test_condition_wait_until();
366 void do_test_condition_wait_until_pred() {
371 boost::fibers::mutex m
;
372 boost::fibers::condition_variable cv
;
374 std::unique_lock
< boost::fibers::mutex
> lk( m
);
375 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn3
, std::ref( m
), std::ref( cv
) );
376 BOOST_CHECK(test1
== 0);
379 BOOST_CHECK(test1
!= 0);
388 std::unique_lock
< boost::fibers::mutex
> lk( m
);
389 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn3
, std::ref( m
), std::ref( cv
) );
390 BOOST_CHECK(test1
== 0);
393 BOOST_CHECK(test1
!= 0);
399 void test_condition_wait_until_pred() {
400 boost::fibers::fiber( boost::fibers::launch::dispatch
, & do_test_condition_wait_until_pred
).join();
401 do_test_condition_wait_until_pred();
404 void do_test_condition_wait_for() {
409 boost::fibers::mutex m
;
410 boost::fibers::condition_variable cv
;
412 std::unique_lock
< boost::fibers::mutex
> lk( m
);
413 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn4
, std::ref( m
), std::ref( cv
) );
414 BOOST_CHECK(test1
== 0);
417 BOOST_CHECK(test1
!= 0);
426 std::unique_lock
< boost::fibers::mutex
> lk( m
);
427 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn4
, std::ref( m
), std::ref( cv
) );
428 BOOST_CHECK(test1
== 0);
431 BOOST_CHECK(test1
!= 0);
437 void test_condition_wait_for() {
438 boost::fibers::fiber( boost::fibers::launch::dispatch
, & do_test_condition_wait_for
).join();
439 do_test_condition_wait_for();
442 void do_test_condition_wait_for_pred() {
447 boost::fibers::mutex m
;
448 boost::fibers::condition_variable cv
;
450 std::unique_lock
< boost::fibers::mutex
> lk( m
);
451 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn5
, std::ref( m
), std::ref( cv
) );
452 BOOST_CHECK(test1
== 0);
455 BOOST_CHECK(test1
!= 0);
464 std::unique_lock
< boost::fibers::mutex
> lk( m
);
465 boost::fibers::fiber
f( boost::fibers::launch::dispatch
, & fn5
, std::ref( m
), std::ref( cv
) );
466 BOOST_CHECK(test1
== 0);
469 BOOST_CHECK(test1
!= 0);
475 void test_condition_wait_for_pred() {
476 boost::fibers::fiber( boost::fibers::launch::dispatch
, & do_test_condition_wait_for_pred
).join();
477 do_test_condition_wait_for_pred();
480 boost::unit_test::test_suite
* init_unit_test_suite( int, char* [])
482 boost::unit_test::test_suite
* test
=
483 BOOST_TEST_SUITE("Boost.Fiber: condition_variable test suite");
485 test
->add( BOOST_TEST_CASE( & test_one_waiter_notify_one
) );
486 test
->add( BOOST_TEST_CASE( & test_two_waiter_notify_one
) );
487 test
->add( BOOST_TEST_CASE( & test_two_waiter_notify_all
) );
488 test
->add( BOOST_TEST_CASE( & test_condition_wait
) );
489 test
->add( BOOST_TEST_CASE( & test_condition_wait_until
) );
490 test
->add( BOOST_TEST_CASE( & test_condition_wait_until_pred
) );
491 test
->add( BOOST_TEST_CASE( & test_condition_wait_for
) );
492 test
->add( BOOST_TEST_CASE( & test_condition_wait_for_pred
) );