]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
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) | |
6 | // | |
7 | // This test is based on the tests of Boost.Thread | |
8 | ||
9 | #include <cstdio> | |
10 | #include <cstdlib> | |
11 | #include <iostream> | |
12 | #include <map> | |
13 | #include <mutex> | |
14 | #include <stdexcept> | |
15 | #include <vector> | |
16 | ||
17 | #include <boost/atomic.hpp> | |
18 | #include <boost/bind.hpp> | |
19 | #include <boost/chrono.hpp> | |
20 | #include <boost/cstdint.hpp> | |
21 | #include <boost/function.hpp> | |
22 | #include <boost/ref.hpp> | |
23 | #include <boost/test/unit_test.hpp> | |
24 | #include <boost/thread.hpp> | |
25 | #include <boost/utility.hpp> | |
26 | ||
27 | #include <boost/fiber/all.hpp> | |
28 | ||
29 | typedef boost::chrono::milliseconds ms; | |
30 | ||
b32b8144 | 31 | boost::atomic< int > value1; |
7c673cae FG |
32 | |
33 | void wait_fn( boost::barrier & b, | |
34 | boost::fibers::mutex & mtx, | |
35 | boost::fibers::condition_variable & cond, | |
36 | bool & flag) { | |
37 | b.wait(); | |
38 | std::unique_lock< boost::fibers::mutex > lk( mtx); | |
39 | cond.wait( lk, [&flag](){ return flag; }); | |
b32b8144 | 40 | ++value1; |
7c673cae FG |
41 | } |
42 | ||
43 | void notify_one_fn( boost::barrier & b, | |
44 | boost::fibers::mutex & mtx, | |
45 | boost::fibers::condition_variable & cond, | |
46 | bool & flag) { | |
47 | b.wait(); | |
48 | std::unique_lock< boost::fibers::mutex > lk( mtx); | |
49 | flag = true; | |
50 | lk.unlock(); | |
51 | cond.notify_one(); | |
52 | } | |
53 | ||
54 | void notify_all_fn( boost::barrier & b, | |
55 | boost::fibers::mutex & mtx, | |
56 | boost::fibers::condition_variable & cond, | |
57 | bool & flag) { | |
58 | b.wait(); | |
59 | std::unique_lock< boost::fibers::mutex > lk( mtx); | |
60 | flag = true; | |
61 | lk.unlock(); | |
62 | cond.notify_all(); | |
63 | } | |
64 | ||
65 | void fn1( boost::barrier & b, | |
66 | boost::fibers::mutex & mtx, | |
67 | boost::fibers::condition_variable & cond, | |
68 | bool & flag) { | |
69 | boost::fibers::fiber( | |
70 | boost::fibers::launch::post, | |
71 | wait_fn, | |
72 | std::ref( b), | |
73 | std::ref( mtx), | |
74 | std::ref( cond), | |
75 | std::ref( flag) ).join(); | |
76 | } | |
77 | ||
78 | void fn2( boost::barrier & b, | |
79 | boost::fibers::mutex & mtx, | |
80 | boost::fibers::condition_variable & cond, | |
81 | bool & flag) { | |
82 | boost::fibers::fiber( | |
83 | boost::fibers::launch::post, | |
84 | notify_one_fn, | |
85 | std::ref( b), | |
86 | std::ref( mtx), | |
87 | std::ref( cond), | |
88 | std::ref( flag) ).join(); | |
89 | } | |
90 | ||
91 | void fn3( boost::barrier & b, | |
92 | boost::fibers::mutex & mtx, | |
93 | boost::fibers::condition_variable & cond, | |
94 | bool & flag) { | |
95 | boost::fibers::fiber( | |
96 | boost::fibers::launch::post, | |
97 | notify_all_fn, | |
98 | std::ref( b), | |
99 | std::ref( mtx), | |
100 | std::ref( cond), | |
101 | std::ref( flag) ).join(); | |
102 | } | |
103 | ||
104 | void test_one_waiter_notify_one() { | |
105 | for ( int i = 0; i < 10; ++i) { | |
106 | boost::barrier b( 2); | |
107 | ||
108 | bool flag = false; | |
b32b8144 | 109 | value1 = 0; |
7c673cae FG |
110 | boost::fibers::mutex mtx; |
111 | boost::fibers::condition_variable cond; | |
112 | ||
b32b8144 | 113 | BOOST_CHECK( 0 == value1); |
7c673cae FG |
114 | |
115 | boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) ); | |
116 | boost::thread t2(std::bind( fn2, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) ); | |
117 | ||
118 | t1.join(); | |
119 | t2.join(); | |
120 | ||
b32b8144 | 121 | BOOST_CHECK( 1 == value1); |
7c673cae FG |
122 | } |
123 | } | |
124 | ||
125 | void test_two_waiter_notify_all() { | |
126 | for ( int i = 0; i < 10; ++i) { | |
127 | boost::barrier b( 3); | |
128 | ||
129 | bool flag = false; | |
b32b8144 | 130 | value1 = 0; |
7c673cae FG |
131 | boost::fibers::mutex mtx; |
132 | boost::fibers::condition_variable cond; | |
133 | ||
b32b8144 | 134 | BOOST_CHECK( 0 == value1); |
7c673cae FG |
135 | |
136 | boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) ); | |
137 | boost::thread t2(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) ); | |
138 | boost::thread t3(std::bind( fn3, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) ); | |
139 | ||
140 | t1.join(); | |
141 | t2.join(); | |
142 | t3.join(); | |
143 | ||
b32b8144 | 144 | BOOST_CHECK( 2 == value1); |
7c673cae FG |
145 | } |
146 | } | |
147 | ||
148 | void test_dummy() { | |
149 | } | |
150 | ||
151 | boost::unit_test::test_suite * init_unit_test_suite( int, char* []) | |
152 | { | |
153 | boost::unit_test::test_suite * test = | |
154 | BOOST_TEST_SUITE("Boost.Fiber: multithreaded condition_variable test suite"); | |
155 | ||
156 | #if ! defined(BOOST_FIBERS_NO_ATOMICS) | |
157 | test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) ); | |
158 | test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) ); | |
159 | #else | |
160 | test->add( BOOST_TEST_CASE( & test_dummy) ); | |
161 | #endif | |
162 | ||
163 | return test; | |
164 | } |