]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // |
2 | // compose.cpp | |
3 | // ~~~~~~~~~~~ | |
4 | // | |
f67539c2 | 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
92f5a8d4 TL |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | // Disable autolinking for unit tests. | |
12 | #if !defined(BOOST_ALL_NO_LIB) | |
13 | #define BOOST_ALL_NO_LIB 1 | |
14 | #endif // !defined(BOOST_ALL_NO_LIB) | |
15 | ||
16 | // Test that header file is self-contained. | |
17 | #include <boost/asio/compose.hpp> | |
18 | ||
19 | #include "unit_test.hpp" | |
20 | ||
21 | #include <boost/asio/io_context.hpp> | |
22 | #include <boost/asio/post.hpp> | |
23 | ||
24 | #if defined(BOOST_ASIO_HAS_BOOST_BIND) | |
f67539c2 | 25 | # include <boost/bind/bind.hpp> |
92f5a8d4 TL |
26 | #else // defined(BOOST_ASIO_HAS_BOOST_BIND) |
27 | # include <functional> | |
28 | #endif // defined(BOOST_ASIO_HAS_BOOST_BIND) | |
29 | ||
30 | //------------------------------------------------------------------------------ | |
31 | ||
32 | class impl_0_completion_args | |
33 | { | |
34 | public: | |
35 | explicit impl_0_completion_args(boost::asio::io_context& ioc) | |
36 | : ioc_(ioc), | |
37 | state_(starting) | |
38 | { | |
39 | } | |
40 | ||
41 | template <typename Self> | |
42 | void operator()(Self& self) | |
43 | { | |
44 | switch (state_) | |
45 | { | |
46 | case starting: | |
47 | state_ = posting; | |
48 | boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self)); | |
49 | break; | |
50 | case posting: | |
51 | self.complete(); | |
52 | break; | |
53 | default: | |
54 | break; | |
55 | } | |
56 | } | |
57 | ||
58 | private: | |
59 | boost::asio::io_context& ioc_; | |
60 | enum { starting, posting } state_; | |
61 | }; | |
62 | ||
63 | template <typename CompletionToken> | |
64 | BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) | |
65 | async_0_completion_args(boost::asio::io_context& ioc, | |
66 | BOOST_ASIO_MOVE_ARG(CompletionToken) token) | |
67 | { | |
68 | return boost::asio::async_compose<CompletionToken, void()>( | |
69 | impl_0_completion_args(ioc), token); | |
70 | } | |
71 | ||
72 | void compose_0_args_handler(int* count) | |
73 | { | |
74 | ++(*count); | |
75 | } | |
76 | ||
20effc67 TL |
77 | struct compose_0_args_lvalue_handler |
78 | { | |
79 | int* count_; | |
80 | ||
81 | void operator()() | |
82 | { | |
83 | ++(*count_); | |
84 | } | |
85 | }; | |
86 | ||
92f5a8d4 TL |
87 | void compose_0_completion_args_test() |
88 | { | |
89 | #if defined(BOOST_ASIO_HAS_BOOST_BIND) | |
90 | namespace bindns = boost; | |
91 | #else // defined(BOOST_ASIO_HAS_BOOST_BIND) | |
92 | namespace bindns = std; | |
93 | #endif // defined(BOOST_ASIO_HAS_BOOST_BIND) | |
94 | ||
95 | boost::asio::io_context ioc; | |
96 | int count = 0; | |
97 | ||
98 | async_0_completion_args(ioc, bindns::bind(&compose_0_args_handler, &count)); | |
99 | ||
100 | // No handlers can be called until run() is called. | |
101 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
102 | BOOST_ASIO_CHECK(count == 0); | |
103 | ||
104 | ioc.run(); | |
105 | ||
106 | // The run() call will not return until all work has finished. | |
107 | BOOST_ASIO_CHECK(ioc.stopped()); | |
108 | BOOST_ASIO_CHECK(count == 1); | |
20effc67 TL |
109 | |
110 | ioc.restart(); | |
111 | count = 0; | |
112 | ||
113 | compose_0_args_lvalue_handler lvalue_handler = { &count }; | |
114 | async_0_completion_args(ioc, lvalue_handler); | |
115 | ||
116 | // No handlers can be called until run() is called. | |
117 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
118 | BOOST_ASIO_CHECK(count == 0); | |
119 | ||
120 | ioc.run(); | |
121 | ||
122 | // The run() call will not return until all work has finished. | |
123 | BOOST_ASIO_CHECK(ioc.stopped()); | |
124 | BOOST_ASIO_CHECK(count == 1); | |
92f5a8d4 TL |
125 | } |
126 | ||
127 | //------------------------------------------------------------------------------ | |
128 | ||
129 | class impl_1_completion_arg | |
130 | { | |
131 | public: | |
132 | explicit impl_1_completion_arg(boost::asio::io_context& ioc) | |
133 | : ioc_(ioc), | |
134 | state_(starting) | |
135 | { | |
136 | } | |
137 | ||
138 | template <typename Self> | |
139 | void operator()(Self& self) | |
140 | { | |
141 | switch (state_) | |
142 | { | |
143 | case starting: | |
144 | state_ = posting; | |
145 | boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self)); | |
146 | break; | |
147 | case posting: | |
148 | self.complete(42); | |
149 | break; | |
150 | default: | |
151 | break; | |
152 | } | |
153 | } | |
154 | ||
155 | private: | |
156 | boost::asio::io_context& ioc_; | |
157 | enum { starting, posting } state_; | |
158 | }; | |
159 | ||
160 | template <typename CompletionToken> | |
161 | BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int)) | |
162 | async_1_completion_arg(boost::asio::io_context& ioc, | |
163 | BOOST_ASIO_MOVE_ARG(CompletionToken) token) | |
164 | { | |
165 | return boost::asio::async_compose<CompletionToken, void(int)>( | |
166 | impl_1_completion_arg(ioc), token); | |
167 | } | |
168 | ||
20effc67 | 169 | void compose_1_arg_handler(int* count, int* result_out, int result) |
92f5a8d4 TL |
170 | { |
171 | ++(*count); | |
172 | *result_out = result; | |
173 | } | |
174 | ||
20effc67 TL |
175 | struct compose_1_arg_lvalue_handler |
176 | { | |
177 | int* count_; | |
178 | int* result_out_; | |
179 | ||
180 | void operator()(int result) | |
181 | { | |
182 | ++(*count_); | |
183 | *result_out_ = result; | |
184 | } | |
185 | }; | |
186 | ||
92f5a8d4 TL |
187 | void compose_1_completion_arg_test() |
188 | { | |
189 | #if defined(BOOST_ASIO_HAS_BOOST_BIND) | |
190 | namespace bindns = boost; | |
191 | #else // defined(BOOST_ASIO_HAS_BOOST_BIND) | |
192 | namespace bindns = std; | |
92f5a8d4 | 193 | #endif // defined(BOOST_ASIO_HAS_BOOST_BIND) |
f67539c2 | 194 | using bindns::placeholders::_1; |
92f5a8d4 TL |
195 | |
196 | boost::asio::io_context ioc; | |
197 | int count = 0; | |
198 | int result = 0; | |
199 | ||
200 | async_1_completion_arg(ioc, | |
20effc67 TL |
201 | bindns::bind(&compose_1_arg_handler, &count, &result, _1)); |
202 | ||
203 | // No handlers can be called until run() is called. | |
204 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
205 | BOOST_ASIO_CHECK(count == 0); | |
206 | BOOST_ASIO_CHECK(result == 0); | |
207 | ||
208 | ioc.run(); | |
209 | ||
210 | // The run() call will not return until all work has finished. | |
211 | BOOST_ASIO_CHECK(ioc.stopped()); | |
212 | BOOST_ASIO_CHECK(count == 1); | |
213 | BOOST_ASIO_CHECK(result == 42); | |
214 | ||
215 | ioc.restart(); | |
216 | count = 0; | |
217 | result = 0; | |
218 | ||
219 | compose_1_arg_lvalue_handler lvalue_handler = { &count, &result }; | |
220 | async_1_completion_arg(ioc, lvalue_handler); | |
92f5a8d4 TL |
221 | |
222 | // No handlers can be called until run() is called. | |
223 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
224 | BOOST_ASIO_CHECK(count == 0); | |
225 | BOOST_ASIO_CHECK(result == 0); | |
226 | ||
227 | ioc.run(); | |
228 | ||
229 | // The run() call will not return until all work has finished. | |
230 | BOOST_ASIO_CHECK(ioc.stopped()); | |
231 | BOOST_ASIO_CHECK(count == 1); | |
232 | BOOST_ASIO_CHECK(result == 42); | |
233 | } | |
234 | ||
235 | //------------------------------------------------------------------------------ | |
236 | ||
237 | BOOST_ASIO_TEST_SUITE | |
238 | ( | |
239 | "compose", | |
240 | BOOST_ASIO_TEST_CASE(compose_0_completion_args_test) | |
241 | BOOST_ASIO_TEST_CASE(compose_1_completion_arg_test) | |
242 | ) |