]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // impl/read.hpp | |
3 | // ~~~~~~~~~~~~~ | |
4 | // | |
f67539c2 | 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
b32b8144 FG |
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 | #ifndef BOOST_ASIO_IMPL_READ_HPP | |
12 | #define BOOST_ASIO_IMPL_READ_HPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <algorithm> | |
19 | #include <boost/asio/associated_allocator.hpp> | |
20 | #include <boost/asio/associated_executor.hpp> | |
21 | #include <boost/asio/buffer.hpp> | |
22 | #include <boost/asio/completion_condition.hpp> | |
23 | #include <boost/asio/detail/array_fwd.hpp> | |
24 | #include <boost/asio/detail/base_from_completion_cond.hpp> | |
25 | #include <boost/asio/detail/bind_handler.hpp> | |
26 | #include <boost/asio/detail/consuming_buffers.hpp> | |
27 | #include <boost/asio/detail/dependent_type.hpp> | |
28 | #include <boost/asio/detail/handler_alloc_helpers.hpp> | |
29 | #include <boost/asio/detail/handler_cont_helpers.hpp> | |
30 | #include <boost/asio/detail/handler_invoke_helpers.hpp> | |
31 | #include <boost/asio/detail/handler_type_requirements.hpp> | |
92f5a8d4 | 32 | #include <boost/asio/detail/non_const_lvalue.hpp> |
b32b8144 FG |
33 | #include <boost/asio/detail/throw_error.hpp> |
34 | #include <boost/asio/error.hpp> | |
35 | ||
36 | #include <boost/asio/detail/push_options.hpp> | |
37 | ||
38 | namespace boost { | |
39 | namespace asio { | |
40 | ||
41 | namespace detail | |
42 | { | |
43 | template <typename SyncReadStream, typename MutableBufferSequence, | |
44 | typename MutableBufferIterator, typename CompletionCondition> | |
45 | std::size_t read_buffer_sequence(SyncReadStream& s, | |
46 | const MutableBufferSequence& buffers, const MutableBufferIterator&, | |
47 | CompletionCondition completion_condition, boost::system::error_code& ec) | |
48 | { | |
49 | ec = boost::system::error_code(); | |
50 | boost::asio::detail::consuming_buffers<mutable_buffer, | |
51 | MutableBufferSequence, MutableBufferIterator> tmp(buffers); | |
52 | while (!tmp.empty()) | |
53 | { | |
54 | if (std::size_t max_size = detail::adapt_completion_condition_result( | |
55 | completion_condition(ec, tmp.total_consumed()))) | |
56 | tmp.consume(s.read_some(tmp.prepare(max_size), ec)); | |
57 | else | |
58 | break; | |
59 | } | |
60 | return tmp.total_consumed();; | |
61 | } | |
62 | } // namespace detail | |
63 | ||
64 | template <typename SyncReadStream, typename MutableBufferSequence, | |
65 | typename CompletionCondition> | |
66 | std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, | |
67 | CompletionCondition completion_condition, boost::system::error_code& ec, | |
68 | typename enable_if< | |
69 | is_mutable_buffer_sequence<MutableBufferSequence>::value | |
70 | >::type*) | |
71 | { | |
72 | return detail::read_buffer_sequence(s, buffers, | |
92f5a8d4 TL |
73 | boost::asio::buffer_sequence_begin(buffers), |
74 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
b32b8144 FG |
75 | } |
76 | ||
77 | template <typename SyncReadStream, typename MutableBufferSequence> | |
78 | inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, | |
79 | typename enable_if< | |
80 | is_mutable_buffer_sequence<MutableBufferSequence>::value | |
81 | >::type*) | |
82 | { | |
83 | boost::system::error_code ec; | |
84 | std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec); | |
85 | boost::asio::detail::throw_error(ec, "read"); | |
86 | return bytes_transferred; | |
87 | } | |
88 | ||
89 | template <typename SyncReadStream, typename MutableBufferSequence> | |
90 | inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, | |
91 | boost::system::error_code& ec, | |
92 | typename enable_if< | |
93 | is_mutable_buffer_sequence<MutableBufferSequence>::value | |
94 | >::type*) | |
95 | { | |
96 | return read(s, buffers, transfer_all(), ec); | |
97 | } | |
98 | ||
99 | template <typename SyncReadStream, typename MutableBufferSequence, | |
100 | typename CompletionCondition> | |
101 | inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, | |
102 | CompletionCondition completion_condition, | |
103 | typename enable_if< | |
104 | is_mutable_buffer_sequence<MutableBufferSequence>::value | |
105 | >::type*) | |
106 | { | |
107 | boost::system::error_code ec; | |
92f5a8d4 TL |
108 | std::size_t bytes_transferred = read(s, buffers, |
109 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
b32b8144 FG |
110 | boost::asio::detail::throw_error(ec, "read"); |
111 | return bytes_transferred; | |
112 | } | |
113 | ||
92f5a8d4 TL |
114 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
115 | ||
116 | template <typename SyncReadStream, typename DynamicBuffer_v1, | |
b32b8144 FG |
117 | typename CompletionCondition> |
118 | std::size_t read(SyncReadStream& s, | |
92f5a8d4 | 119 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, |
b32b8144 FG |
120 | CompletionCondition completion_condition, boost::system::error_code& ec, |
121 | typename enable_if< | |
92f5a8d4 TL |
122 | is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value |
123 | && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value | |
b32b8144 FG |
124 | >::type*) |
125 | { | |
92f5a8d4 TL |
126 | typename decay<DynamicBuffer_v1>::type b( |
127 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); | |
b32b8144 FG |
128 | |
129 | ec = boost::system::error_code(); | |
130 | std::size_t total_transferred = 0; | |
131 | std::size_t max_size = detail::adapt_completion_condition_result( | |
132 | completion_condition(ec, total_transferred)); | |
133 | std::size_t bytes_available = std::min<std::size_t>( | |
134 | std::max<std::size_t>(512, b.capacity() - b.size()), | |
135 | std::min<std::size_t>(max_size, b.max_size() - b.size())); | |
136 | while (bytes_available > 0) | |
137 | { | |
138 | std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec); | |
139 | b.commit(bytes_transferred); | |
140 | total_transferred += bytes_transferred; | |
141 | max_size = detail::adapt_completion_condition_result( | |
142 | completion_condition(ec, total_transferred)); | |
143 | bytes_available = std::min<std::size_t>( | |
144 | std::max<std::size_t>(512, b.capacity() - b.size()), | |
145 | std::min<std::size_t>(max_size, b.max_size() - b.size())); | |
146 | } | |
147 | return total_transferred; | |
148 | } | |
149 | ||
92f5a8d4 | 150 | template <typename SyncReadStream, typename DynamicBuffer_v1> |
b32b8144 | 151 | inline std::size_t read(SyncReadStream& s, |
92f5a8d4 | 152 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, |
b32b8144 | 153 | typename enable_if< |
92f5a8d4 TL |
154 | is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value |
155 | && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value | |
b32b8144 FG |
156 | >::type*) |
157 | { | |
158 | boost::system::error_code ec; | |
159 | std::size_t bytes_transferred = read(s, | |
92f5a8d4 | 160 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec); |
b32b8144 FG |
161 | boost::asio::detail::throw_error(ec, "read"); |
162 | return bytes_transferred; | |
163 | } | |
164 | ||
92f5a8d4 | 165 | template <typename SyncReadStream, typename DynamicBuffer_v1> |
b32b8144 | 166 | inline std::size_t read(SyncReadStream& s, |
92f5a8d4 | 167 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, |
b32b8144 FG |
168 | boost::system::error_code& ec, |
169 | typename enable_if< | |
92f5a8d4 TL |
170 | is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value |
171 | && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value | |
b32b8144 FG |
172 | >::type*) |
173 | { | |
92f5a8d4 | 174 | return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), |
b32b8144 FG |
175 | transfer_all(), ec); |
176 | } | |
177 | ||
92f5a8d4 | 178 | template <typename SyncReadStream, typename DynamicBuffer_v1, |
b32b8144 FG |
179 | typename CompletionCondition> |
180 | inline std::size_t read(SyncReadStream& s, | |
92f5a8d4 | 181 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, |
b32b8144 FG |
182 | CompletionCondition completion_condition, |
183 | typename enable_if< | |
92f5a8d4 TL |
184 | is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value |
185 | && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value | |
b32b8144 FG |
186 | >::type*) |
187 | { | |
188 | boost::system::error_code ec; | |
189 | std::size_t bytes_transferred = read(s, | |
92f5a8d4 TL |
190 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), |
191 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
b32b8144 FG |
192 | boost::asio::detail::throw_error(ec, "read"); |
193 | return bytes_transferred; | |
194 | } | |
195 | ||
196 | #if !defined(BOOST_ASIO_NO_EXTENSIONS) | |
197 | #if !defined(BOOST_ASIO_NO_IOSTREAM) | |
198 | ||
199 | template <typename SyncReadStream, typename Allocator, | |
200 | typename CompletionCondition> | |
201 | inline std::size_t read(SyncReadStream& s, | |
202 | boost::asio::basic_streambuf<Allocator>& b, | |
203 | CompletionCondition completion_condition, boost::system::error_code& ec) | |
204 | { | |
92f5a8d4 TL |
205 | return read(s, basic_streambuf_ref<Allocator>(b), |
206 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
b32b8144 FG |
207 | } |
208 | ||
209 | template <typename SyncReadStream, typename Allocator> | |
210 | inline std::size_t read(SyncReadStream& s, | |
211 | boost::asio::basic_streambuf<Allocator>& b) | |
212 | { | |
213 | return read(s, basic_streambuf_ref<Allocator>(b)); | |
214 | } | |
215 | ||
216 | template <typename SyncReadStream, typename Allocator> | |
217 | inline std::size_t read(SyncReadStream& s, | |
218 | boost::asio::basic_streambuf<Allocator>& b, | |
219 | boost::system::error_code& ec) | |
220 | { | |
221 | return read(s, basic_streambuf_ref<Allocator>(b), ec); | |
222 | } | |
223 | ||
224 | template <typename SyncReadStream, typename Allocator, | |
225 | typename CompletionCondition> | |
226 | inline std::size_t read(SyncReadStream& s, | |
227 | boost::asio::basic_streambuf<Allocator>& b, | |
228 | CompletionCondition completion_condition) | |
229 | { | |
92f5a8d4 TL |
230 | return read(s, basic_streambuf_ref<Allocator>(b), |
231 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); | |
b32b8144 FG |
232 | } |
233 | ||
234 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) | |
235 | #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) | |
92f5a8d4 TL |
236 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
237 | ||
238 | template <typename SyncReadStream, typename DynamicBuffer_v2, | |
239 | typename CompletionCondition> | |
240 | std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, | |
241 | CompletionCondition completion_condition, boost::system::error_code& ec, | |
242 | typename enable_if< | |
243 | is_dynamic_buffer_v2<DynamicBuffer_v2>::value | |
244 | >::type*) | |
245 | { | |
246 | DynamicBuffer_v2& b = buffers; | |
247 | ||
248 | ec = boost::system::error_code(); | |
249 | std::size_t total_transferred = 0; | |
250 | std::size_t max_size = detail::adapt_completion_condition_result( | |
251 | completion_condition(ec, total_transferred)); | |
252 | std::size_t bytes_available = std::min<std::size_t>( | |
253 | std::max<std::size_t>(512, b.capacity() - b.size()), | |
254 | std::min<std::size_t>(max_size, b.max_size() - b.size())); | |
255 | while (bytes_available > 0) | |
256 | { | |
257 | std::size_t pos = b.size(); | |
258 | b.grow(bytes_available); | |
259 | std::size_t bytes_transferred = s.read_some( | |
260 | b.data(pos, bytes_available), ec); | |
261 | b.shrink(bytes_available - bytes_transferred); | |
262 | total_transferred += bytes_transferred; | |
263 | max_size = detail::adapt_completion_condition_result( | |
264 | completion_condition(ec, total_transferred)); | |
265 | bytes_available = std::min<std::size_t>( | |
266 | std::max<std::size_t>(512, b.capacity() - b.size()), | |
267 | std::min<std::size_t>(max_size, b.max_size() - b.size())); | |
268 | } | |
269 | return total_transferred; | |
270 | } | |
271 | ||
272 | template <typename SyncReadStream, typename DynamicBuffer_v2> | |
273 | inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, | |
274 | typename enable_if< | |
275 | is_dynamic_buffer_v2<DynamicBuffer_v2>::value | |
276 | >::type*) | |
277 | { | |
278 | boost::system::error_code ec; | |
279 | std::size_t bytes_transferred = read(s, | |
280 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec); | |
281 | boost::asio::detail::throw_error(ec, "read"); | |
282 | return bytes_transferred; | |
283 | } | |
284 | ||
285 | template <typename SyncReadStream, typename DynamicBuffer_v2> | |
286 | inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, | |
287 | boost::system::error_code& ec, | |
288 | typename enable_if< | |
289 | is_dynamic_buffer_v2<DynamicBuffer_v2>::value | |
290 | >::type*) | |
291 | { | |
292 | return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), | |
293 | transfer_all(), ec); | |
294 | } | |
295 | ||
296 | template <typename SyncReadStream, typename DynamicBuffer_v2, | |
297 | typename CompletionCondition> | |
298 | inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, | |
299 | CompletionCondition completion_condition, | |
300 | typename enable_if< | |
301 | is_dynamic_buffer_v2<DynamicBuffer_v2>::value | |
302 | >::type*) | |
303 | { | |
304 | boost::system::error_code ec; | |
305 | std::size_t bytes_transferred = read(s, | |
306 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), | |
307 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); | |
308 | boost::asio::detail::throw_error(ec, "read"); | |
309 | return bytes_transferred; | |
310 | } | |
b32b8144 FG |
311 | |
312 | namespace detail | |
313 | { | |
314 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
315 | typename MutableBufferIterator, typename CompletionCondition, | |
316 | typename ReadHandler> | |
317 | class read_op | |
318 | : detail::base_from_completion_cond<CompletionCondition> | |
319 | { | |
320 | public: | |
321 | read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, | |
92f5a8d4 | 322 | CompletionCondition& completion_condition, ReadHandler& handler) |
b32b8144 FG |
323 | : detail::base_from_completion_cond< |
324 | CompletionCondition>(completion_condition), | |
325 | stream_(stream), | |
326 | buffers_(buffers), | |
327 | start_(0), | |
328 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) | |
329 | { | |
330 | } | |
331 | ||
332 | #if defined(BOOST_ASIO_HAS_MOVE) | |
333 | read_op(const read_op& other) | |
334 | : detail::base_from_completion_cond<CompletionCondition>(other), | |
335 | stream_(other.stream_), | |
336 | buffers_(other.buffers_), | |
337 | start_(other.start_), | |
338 | handler_(other.handler_) | |
339 | { | |
340 | } | |
341 | ||
342 | read_op(read_op&& other) | |
92f5a8d4 TL |
343 | : detail::base_from_completion_cond<CompletionCondition>( |
344 | BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< | |
345 | CompletionCondition>)(other)), | |
b32b8144 | 346 | stream_(other.stream_), |
92f5a8d4 | 347 | buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)), |
b32b8144 FG |
348 | start_(other.start_), |
349 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) | |
350 | { | |
351 | } | |
352 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
353 | ||
354 | void operator()(const boost::system::error_code& ec, | |
355 | std::size_t bytes_transferred, int start = 0) | |
356 | { | |
357 | std::size_t max_size; | |
358 | switch (start_ = start) | |
359 | { | |
360 | case 1: | |
361 | max_size = this->check_for_completion(ec, buffers_.total_consumed()); | |
362 | do | |
363 | { | |
364 | stream_.async_read_some(buffers_.prepare(max_size), | |
365 | BOOST_ASIO_MOVE_CAST(read_op)(*this)); | |
366 | return; default: | |
367 | buffers_.consume(bytes_transferred); | |
368 | if ((!ec && bytes_transferred == 0) || buffers_.empty()) | |
369 | break; | |
370 | max_size = this->check_for_completion(ec, buffers_.total_consumed()); | |
371 | } while (max_size > 0); | |
372 | ||
373 | handler_(ec, buffers_.total_consumed()); | |
374 | } | |
375 | } | |
376 | ||
377 | //private: | |
92f5a8d4 TL |
378 | typedef boost::asio::detail::consuming_buffers<mutable_buffer, |
379 | MutableBufferSequence, MutableBufferIterator> buffers_type; | |
380 | ||
b32b8144 | 381 | AsyncReadStream& stream_; |
92f5a8d4 | 382 | buffers_type buffers_; |
b32b8144 FG |
383 | int start_; |
384 | ReadHandler handler_; | |
385 | }; | |
386 | ||
387 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
388 | typename MutableBufferIterator, typename CompletionCondition, | |
389 | typename ReadHandler> | |
390 | inline void* asio_handler_allocate(std::size_t size, | |
391 | read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, | |
392 | CompletionCondition, ReadHandler>* this_handler) | |
393 | { | |
394 | return boost_asio_handler_alloc_helpers::allocate( | |
395 | size, this_handler->handler_); | |
396 | } | |
397 | ||
398 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
399 | typename MutableBufferIterator, typename CompletionCondition, | |
400 | typename ReadHandler> | |
401 | inline void asio_handler_deallocate(void* pointer, std::size_t size, | |
402 | read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, | |
403 | CompletionCondition, ReadHandler>* this_handler) | |
404 | { | |
405 | boost_asio_handler_alloc_helpers::deallocate( | |
406 | pointer, size, this_handler->handler_); | |
407 | } | |
408 | ||
409 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
410 | typename MutableBufferIterator, typename CompletionCondition, | |
411 | typename ReadHandler> | |
412 | inline bool asio_handler_is_continuation( | |
413 | read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, | |
414 | CompletionCondition, ReadHandler>* this_handler) | |
415 | { | |
416 | return this_handler->start_ == 0 ? true | |
417 | : boost_asio_handler_cont_helpers::is_continuation( | |
418 | this_handler->handler_); | |
419 | } | |
420 | ||
421 | template <typename Function, typename AsyncReadStream, | |
422 | typename MutableBufferSequence, typename MutableBufferIterator, | |
423 | typename CompletionCondition, typename ReadHandler> | |
424 | inline void asio_handler_invoke(Function& function, | |
425 | read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, | |
426 | CompletionCondition, ReadHandler>* this_handler) | |
427 | { | |
428 | boost_asio_handler_invoke_helpers::invoke( | |
429 | function, this_handler->handler_); | |
430 | } | |
431 | ||
432 | template <typename Function, typename AsyncReadStream, | |
433 | typename MutableBufferSequence, typename MutableBufferIterator, | |
434 | typename CompletionCondition, typename ReadHandler> | |
435 | inline void asio_handler_invoke(const Function& function, | |
436 | read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, | |
437 | CompletionCondition, ReadHandler>* this_handler) | |
438 | { | |
439 | boost_asio_handler_invoke_helpers::invoke( | |
440 | function, this_handler->handler_); | |
441 | } | |
442 | ||
443 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
444 | typename MutableBufferIterator, typename CompletionCondition, | |
445 | typename ReadHandler> | |
446 | inline void start_read_buffer_sequence_op(AsyncReadStream& stream, | |
447 | const MutableBufferSequence& buffers, const MutableBufferIterator&, | |
92f5a8d4 | 448 | CompletionCondition& completion_condition, ReadHandler& handler) |
b32b8144 FG |
449 | { |
450 | detail::read_op<AsyncReadStream, MutableBufferSequence, | |
451 | MutableBufferIterator, CompletionCondition, ReadHandler>( | |
452 | stream, buffers, completion_condition, handler)( | |
453 | boost::system::error_code(), 0, 1); | |
454 | } | |
92f5a8d4 TL |
455 | |
456 | template <typename AsyncReadStream> | |
457 | class initiate_async_read_buffer_sequence | |
458 | { | |
459 | public: | |
460 | typedef typename AsyncReadStream::executor_type executor_type; | |
461 | ||
462 | explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream) | |
463 | : stream_(stream) | |
464 | { | |
465 | } | |
466 | ||
467 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
468 | { | |
469 | return stream_.get_executor(); | |
470 | } | |
471 | ||
472 | template <typename ReadHandler, typename MutableBufferSequence, | |
473 | typename CompletionCondition> | |
474 | void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
475 | const MutableBufferSequence& buffers, | |
476 | BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const | |
477 | { | |
478 | // If you get an error on the following line it means that your handler | |
479 | // does not meet the documented type requirements for a ReadHandler. | |
480 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; | |
481 | ||
482 | non_const_lvalue<ReadHandler> handler2(handler); | |
483 | non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); | |
484 | start_read_buffer_sequence_op(stream_, buffers, | |
485 | boost::asio::buffer_sequence_begin(buffers), | |
486 | completion_cond2.value, handler2.value); | |
487 | } | |
488 | ||
489 | private: | |
490 | AsyncReadStream& stream_; | |
491 | }; | |
b32b8144 FG |
492 | } // namespace detail |
493 | ||
494 | #if !defined(GENERATING_DOCUMENTATION) | |
495 | ||
496 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
497 | typename MutableBufferIterator, typename CompletionCondition, | |
498 | typename ReadHandler, typename Allocator> | |
499 | struct associated_allocator< | |
500 | detail::read_op<AsyncReadStream, MutableBufferSequence, | |
501 | MutableBufferIterator, CompletionCondition, ReadHandler>, | |
502 | Allocator> | |
503 | { | |
504 | typedef typename associated_allocator<ReadHandler, Allocator>::type type; | |
505 | ||
506 | static type get( | |
507 | const detail::read_op<AsyncReadStream, MutableBufferSequence, | |
508 | MutableBufferIterator, CompletionCondition, ReadHandler>& h, | |
509 | const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT | |
510 | { | |
511 | return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); | |
512 | } | |
513 | }; | |
514 | ||
515 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
516 | typename MutableBufferIterator, typename CompletionCondition, | |
517 | typename ReadHandler, typename Executor> | |
518 | struct associated_executor< | |
519 | detail::read_op<AsyncReadStream, MutableBufferSequence, | |
520 | MutableBufferIterator, CompletionCondition, ReadHandler>, | |
521 | Executor> | |
522 | { | |
523 | typedef typename associated_executor<ReadHandler, Executor>::type type; | |
524 | ||
525 | static type get( | |
526 | const detail::read_op<AsyncReadStream, MutableBufferSequence, | |
527 | MutableBufferIterator, CompletionCondition, ReadHandler>& h, | |
528 | const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT | |
529 | { | |
530 | return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); | |
531 | } | |
532 | }; | |
533 | ||
534 | #endif // !defined(GENERATING_DOCUMENTATION) | |
535 | ||
92f5a8d4 TL |
536 | template <typename AsyncReadStream, |
537 | typename MutableBufferSequence, typename CompletionCondition, | |
538 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
539 | std::size_t)) ReadHandler> | |
540 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
b32b8144 FG |
541 | void (boost::system::error_code, std::size_t)) |
542 | async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, | |
543 | CompletionCondition completion_condition, | |
544 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
545 | typename enable_if< | |
546 | is_mutable_buffer_sequence<MutableBufferSequence>::value | |
547 | >::type*) | |
548 | { | |
92f5a8d4 TL |
549 | return async_initiate<ReadHandler, |
550 | void (boost::system::error_code, std::size_t)>( | |
551 | detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler, | |
552 | buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); | |
b32b8144 FG |
553 | } |
554 | ||
555 | template <typename AsyncReadStream, typename MutableBufferSequence, | |
92f5a8d4 TL |
556 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
557 | std::size_t)) ReadHandler> | |
558 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
b32b8144 FG |
559 | void (boost::system::error_code, std::size_t)) |
560 | async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, | |
561 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
562 | typename enable_if< | |
563 | is_mutable_buffer_sequence<MutableBufferSequence>::value | |
564 | >::type*) | |
565 | { | |
92f5a8d4 TL |
566 | return async_initiate<ReadHandler, |
567 | void (boost::system::error_code, std::size_t)>( | |
568 | detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), | |
569 | handler, buffers, transfer_all()); | |
b32b8144 FG |
570 | } |
571 | ||
92f5a8d4 TL |
572 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
573 | ||
b32b8144 FG |
574 | namespace detail |
575 | { | |
92f5a8d4 | 576 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
b32b8144 | 577 | typename CompletionCondition, typename ReadHandler> |
92f5a8d4 | 578 | class read_dynbuf_v1_op |
b32b8144 FG |
579 | : detail::base_from_completion_cond<CompletionCondition> |
580 | { | |
581 | public: | |
582 | template <typename BufferSequence> | |
92f5a8d4 | 583 | read_dynbuf_v1_op(AsyncReadStream& stream, |
b32b8144 | 584 | BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, |
92f5a8d4 | 585 | CompletionCondition& completion_condition, ReadHandler& handler) |
b32b8144 FG |
586 | : detail::base_from_completion_cond< |
587 | CompletionCondition>(completion_condition), | |
588 | stream_(stream), | |
589 | buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), | |
590 | start_(0), | |
591 | total_transferred_(0), | |
592 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) | |
593 | { | |
594 | } | |
595 | ||
596 | #if defined(BOOST_ASIO_HAS_MOVE) | |
92f5a8d4 | 597 | read_dynbuf_v1_op(const read_dynbuf_v1_op& other) |
b32b8144 FG |
598 | : detail::base_from_completion_cond<CompletionCondition>(other), |
599 | stream_(other.stream_), | |
600 | buffers_(other.buffers_), | |
601 | start_(other.start_), | |
602 | total_transferred_(other.total_transferred_), | |
603 | handler_(other.handler_) | |
604 | { | |
605 | } | |
606 | ||
92f5a8d4 TL |
607 | read_dynbuf_v1_op(read_dynbuf_v1_op&& other) |
608 | : detail::base_from_completion_cond<CompletionCondition>( | |
609 | BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< | |
610 | CompletionCondition>)(other)), | |
b32b8144 | 611 | stream_(other.stream_), |
92f5a8d4 | 612 | buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), |
b32b8144 FG |
613 | start_(other.start_), |
614 | total_transferred_(other.total_transferred_), | |
615 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) | |
616 | { | |
617 | } | |
618 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
619 | ||
620 | void operator()(const boost::system::error_code& ec, | |
621 | std::size_t bytes_transferred, int start = 0) | |
622 | { | |
623 | std::size_t max_size, bytes_available; | |
624 | switch (start_ = start) | |
625 | { | |
626 | case 1: | |
627 | max_size = this->check_for_completion(ec, total_transferred_); | |
628 | bytes_available = std::min<std::size_t>( | |
629 | std::max<std::size_t>(512, | |
630 | buffers_.capacity() - buffers_.size()), | |
631 | std::min<std::size_t>(max_size, | |
632 | buffers_.max_size() - buffers_.size())); | |
633 | for (;;) | |
634 | { | |
635 | stream_.async_read_some(buffers_.prepare(bytes_available), | |
92f5a8d4 | 636 | BOOST_ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this)); |
b32b8144 FG |
637 | return; default: |
638 | total_transferred_ += bytes_transferred; | |
639 | buffers_.commit(bytes_transferred); | |
640 | max_size = this->check_for_completion(ec, total_transferred_); | |
641 | bytes_available = std::min<std::size_t>( | |
642 | std::max<std::size_t>(512, | |
643 | buffers_.capacity() - buffers_.size()), | |
644 | std::min<std::size_t>(max_size, | |
645 | buffers_.max_size() - buffers_.size())); | |
646 | if ((!ec && bytes_transferred == 0) || bytes_available == 0) | |
647 | break; | |
648 | } | |
649 | ||
650 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); | |
651 | } | |
652 | } | |
653 | ||
654 | //private: | |
655 | AsyncReadStream& stream_; | |
92f5a8d4 | 656 | DynamicBuffer_v1 buffers_; |
b32b8144 FG |
657 | int start_; |
658 | std::size_t total_transferred_; | |
659 | ReadHandler handler_; | |
660 | }; | |
661 | ||
92f5a8d4 | 662 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
b32b8144 FG |
663 | typename CompletionCondition, typename ReadHandler> |
664 | inline void* asio_handler_allocate(std::size_t size, | |
92f5a8d4 | 665 | read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, |
b32b8144 FG |
666 | CompletionCondition, ReadHandler>* this_handler) |
667 | { | |
668 | return boost_asio_handler_alloc_helpers::allocate( | |
669 | size, this_handler->handler_); | |
670 | } | |
671 | ||
92f5a8d4 | 672 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
b32b8144 FG |
673 | typename CompletionCondition, typename ReadHandler> |
674 | inline void asio_handler_deallocate(void* pointer, std::size_t size, | |
92f5a8d4 | 675 | read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, |
b32b8144 FG |
676 | CompletionCondition, ReadHandler>* this_handler) |
677 | { | |
678 | boost_asio_handler_alloc_helpers::deallocate( | |
679 | pointer, size, this_handler->handler_); | |
680 | } | |
681 | ||
92f5a8d4 | 682 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
b32b8144 FG |
683 | typename CompletionCondition, typename ReadHandler> |
684 | inline bool asio_handler_is_continuation( | |
92f5a8d4 | 685 | read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, |
b32b8144 FG |
686 | CompletionCondition, ReadHandler>* this_handler) |
687 | { | |
688 | return this_handler->start_ == 0 ? true | |
689 | : boost_asio_handler_cont_helpers::is_continuation( | |
690 | this_handler->handler_); | |
691 | } | |
692 | ||
693 | template <typename Function, typename AsyncReadStream, | |
92f5a8d4 | 694 | typename DynamicBuffer_v1, typename CompletionCondition, |
b32b8144 FG |
695 | typename ReadHandler> |
696 | inline void asio_handler_invoke(Function& function, | |
92f5a8d4 | 697 | read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, |
b32b8144 FG |
698 | CompletionCondition, ReadHandler>* this_handler) |
699 | { | |
700 | boost_asio_handler_invoke_helpers::invoke( | |
701 | function, this_handler->handler_); | |
702 | } | |
703 | ||
704 | template <typename Function, typename AsyncReadStream, | |
92f5a8d4 | 705 | typename DynamicBuffer_v1, typename CompletionCondition, |
b32b8144 FG |
706 | typename ReadHandler> |
707 | inline void asio_handler_invoke(const Function& function, | |
92f5a8d4 | 708 | read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, |
b32b8144 FG |
709 | CompletionCondition, ReadHandler>* this_handler) |
710 | { | |
711 | boost_asio_handler_invoke_helpers::invoke( | |
712 | function, this_handler->handler_); | |
713 | } | |
92f5a8d4 TL |
714 | |
715 | template <typename AsyncReadStream> | |
716 | class initiate_async_read_dynbuf_v1 | |
717 | { | |
718 | public: | |
719 | typedef typename AsyncReadStream::executor_type executor_type; | |
720 | ||
721 | explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream) | |
722 | : stream_(stream) | |
723 | { | |
724 | } | |
725 | ||
726 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
727 | { | |
728 | return stream_.get_executor(); | |
729 | } | |
730 | ||
731 | template <typename ReadHandler, typename DynamicBuffer_v1, | |
732 | typename CompletionCondition> | |
733 | void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
734 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, | |
735 | BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const | |
736 | { | |
737 | // If you get an error on the following line it means that your handler | |
738 | // does not meet the documented type requirements for a ReadHandler. | |
739 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; | |
740 | ||
741 | non_const_lvalue<ReadHandler> handler2(handler); | |
742 | non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); | |
743 | read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type, | |
744 | CompletionCondition, typename decay<ReadHandler>::type>( | |
745 | stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), | |
746 | completion_cond2.value, handler2.value)( | |
747 | boost::system::error_code(), 0, 1); | |
748 | } | |
749 | ||
750 | private: | |
751 | AsyncReadStream& stream_; | |
752 | }; | |
b32b8144 FG |
753 | } // namespace detail |
754 | ||
755 | #if !defined(GENERATING_DOCUMENTATION) | |
756 | ||
92f5a8d4 | 757 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
b32b8144 FG |
758 | typename CompletionCondition, typename ReadHandler, typename Allocator> |
759 | struct associated_allocator< | |
92f5a8d4 TL |
760 | detail::read_dynbuf_v1_op<AsyncReadStream, |
761 | DynamicBuffer_v1, CompletionCondition, ReadHandler>, | |
b32b8144 FG |
762 | Allocator> |
763 | { | |
764 | typedef typename associated_allocator<ReadHandler, Allocator>::type type; | |
765 | ||
766 | static type get( | |
92f5a8d4 TL |
767 | const detail::read_dynbuf_v1_op<AsyncReadStream, |
768 | DynamicBuffer_v1, CompletionCondition, ReadHandler>& h, | |
b32b8144 FG |
769 | const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT |
770 | { | |
771 | return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); | |
772 | } | |
773 | }; | |
774 | ||
92f5a8d4 | 775 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
b32b8144 FG |
776 | typename CompletionCondition, typename ReadHandler, typename Executor> |
777 | struct associated_executor< | |
92f5a8d4 TL |
778 | detail::read_dynbuf_v1_op<AsyncReadStream, |
779 | DynamicBuffer_v1, CompletionCondition, ReadHandler>, | |
b32b8144 FG |
780 | Executor> |
781 | { | |
782 | typedef typename associated_executor<ReadHandler, Executor>::type type; | |
783 | ||
784 | static type get( | |
92f5a8d4 TL |
785 | const detail::read_dynbuf_v1_op<AsyncReadStream, |
786 | DynamicBuffer_v1, CompletionCondition, ReadHandler>& h, | |
b32b8144 FG |
787 | const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT |
788 | { | |
789 | return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); | |
790 | } | |
791 | }; | |
792 | ||
793 | #endif // !defined(GENERATING_DOCUMENTATION) | |
794 | ||
92f5a8d4 TL |
795 | template <typename AsyncReadStream, typename DynamicBuffer_v1, |
796 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
797 | std::size_t)) ReadHandler> | |
798 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
b32b8144 FG |
799 | void (boost::system::error_code, std::size_t)) |
800 | async_read(AsyncReadStream& s, | |
92f5a8d4 | 801 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, |
b32b8144 FG |
802 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler, |
803 | typename enable_if< | |
92f5a8d4 TL |
804 | is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value |
805 | && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value | |
b32b8144 FG |
806 | >::type*) |
807 | { | |
808 | return async_read(s, | |
92f5a8d4 | 809 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), |
b32b8144 FG |
810 | transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); |
811 | } | |
812 | ||
92f5a8d4 TL |
813 | template <typename AsyncReadStream, |
814 | typename DynamicBuffer_v1, typename CompletionCondition, | |
815 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
816 | std::size_t)) ReadHandler> | |
817 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
b32b8144 FG |
818 | void (boost::system::error_code, std::size_t)) |
819 | async_read(AsyncReadStream& s, | |
92f5a8d4 | 820 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, |
b32b8144 FG |
821 | CompletionCondition completion_condition, |
822 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
823 | typename enable_if< | |
92f5a8d4 TL |
824 | is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value |
825 | && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value | |
b32b8144 FG |
826 | >::type*) |
827 | { | |
92f5a8d4 TL |
828 | return async_initiate<ReadHandler, |
829 | void (boost::system::error_code, std::size_t)>( | |
830 | detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s), | |
831 | handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), | |
832 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); | |
b32b8144 FG |
833 | } |
834 | ||
835 | #if !defined(BOOST_ASIO_NO_EXTENSIONS) | |
836 | #if !defined(BOOST_ASIO_NO_IOSTREAM) | |
837 | ||
92f5a8d4 TL |
838 | template <typename AsyncReadStream, typename Allocator, |
839 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
840 | std::size_t)) ReadHandler> | |
841 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
b32b8144 FG |
842 | void (boost::system::error_code, std::size_t)) |
843 | async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, | |
844 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler) | |
845 | { | |
846 | return async_read(s, basic_streambuf_ref<Allocator>(b), | |
847 | BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); | |
848 | } | |
849 | ||
92f5a8d4 TL |
850 | template <typename AsyncReadStream, |
851 | typename Allocator, typename CompletionCondition, | |
852 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
853 | std::size_t)) ReadHandler> | |
854 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
b32b8144 FG |
855 | void (boost::system::error_code, std::size_t)) |
856 | async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, | |
857 | CompletionCondition completion_condition, | |
858 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler) | |
859 | { | |
860 | return async_read(s, basic_streambuf_ref<Allocator>(b), | |
92f5a8d4 TL |
861 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), |
862 | BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); | |
b32b8144 FG |
863 | } |
864 | ||
865 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) | |
866 | #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) | |
92f5a8d4 TL |
867 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
868 | ||
869 | namespace detail | |
870 | { | |
871 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
872 | typename CompletionCondition, typename ReadHandler> | |
873 | class read_dynbuf_v2_op | |
874 | : detail::base_from_completion_cond<CompletionCondition> | |
875 | { | |
876 | public: | |
877 | template <typename BufferSequence> | |
878 | read_dynbuf_v2_op(AsyncReadStream& stream, | |
879 | BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, | |
880 | CompletionCondition& completion_condition, ReadHandler& handler) | |
881 | : detail::base_from_completion_cond< | |
882 | CompletionCondition>(completion_condition), | |
883 | stream_(stream), | |
884 | buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), | |
885 | start_(0), | |
886 | total_transferred_(0), | |
887 | bytes_available_(0), | |
888 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) | |
889 | { | |
890 | } | |
891 | ||
892 | #if defined(BOOST_ASIO_HAS_MOVE) | |
893 | read_dynbuf_v2_op(const read_dynbuf_v2_op& other) | |
894 | : detail::base_from_completion_cond<CompletionCondition>(other), | |
895 | stream_(other.stream_), | |
896 | buffers_(other.buffers_), | |
897 | start_(other.start_), | |
898 | total_transferred_(other.total_transferred_), | |
899 | bytes_available_(other.bytes_available_), | |
900 | handler_(other.handler_) | |
901 | { | |
902 | } | |
903 | ||
904 | read_dynbuf_v2_op(read_dynbuf_v2_op&& other) | |
905 | : detail::base_from_completion_cond<CompletionCondition>( | |
906 | BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< | |
907 | CompletionCondition>)(other)), | |
908 | stream_(other.stream_), | |
909 | buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), | |
910 | start_(other.start_), | |
911 | total_transferred_(other.total_transferred_), | |
912 | bytes_available_(other.bytes_available_), | |
913 | handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) | |
914 | { | |
915 | } | |
916 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
917 | ||
918 | void operator()(const boost::system::error_code& ec, | |
919 | std::size_t bytes_transferred, int start = 0) | |
920 | { | |
921 | std::size_t max_size, pos; | |
922 | switch (start_ = start) | |
923 | { | |
924 | case 1: | |
925 | max_size = this->check_for_completion(ec, total_transferred_); | |
926 | bytes_available_ = std::min<std::size_t>( | |
927 | std::max<std::size_t>(512, | |
928 | buffers_.capacity() - buffers_.size()), | |
929 | std::min<std::size_t>(max_size, | |
930 | buffers_.max_size() - buffers_.size())); | |
931 | for (;;) | |
932 | { | |
933 | pos = buffers_.size(); | |
934 | buffers_.grow(bytes_available_); | |
935 | stream_.async_read_some(buffers_.data(pos, bytes_available_), | |
936 | BOOST_ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this)); | |
937 | return; default: | |
938 | total_transferred_ += bytes_transferred; | |
939 | buffers_.shrink(bytes_available_ - bytes_transferred); | |
940 | max_size = this->check_for_completion(ec, total_transferred_); | |
941 | bytes_available_ = std::min<std::size_t>( | |
942 | std::max<std::size_t>(512, | |
943 | buffers_.capacity() - buffers_.size()), | |
944 | std::min<std::size_t>(max_size, | |
945 | buffers_.max_size() - buffers_.size())); | |
946 | if ((!ec && bytes_transferred == 0) || bytes_available_ == 0) | |
947 | break; | |
948 | } | |
949 | ||
950 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); | |
951 | } | |
952 | } | |
953 | ||
954 | //private: | |
955 | AsyncReadStream& stream_; | |
956 | DynamicBuffer_v2 buffers_; | |
957 | int start_; | |
958 | std::size_t total_transferred_; | |
959 | std::size_t bytes_available_; | |
960 | ReadHandler handler_; | |
961 | }; | |
962 | ||
963 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
964 | typename CompletionCondition, typename ReadHandler> | |
965 | inline void* asio_handler_allocate(std::size_t size, | |
966 | read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, | |
967 | CompletionCondition, ReadHandler>* this_handler) | |
968 | { | |
969 | return boost_asio_handler_alloc_helpers::allocate( | |
970 | size, this_handler->handler_); | |
971 | } | |
972 | ||
973 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
974 | typename CompletionCondition, typename ReadHandler> | |
975 | inline void asio_handler_deallocate(void* pointer, std::size_t size, | |
976 | read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, | |
977 | CompletionCondition, ReadHandler>* this_handler) | |
978 | { | |
979 | boost_asio_handler_alloc_helpers::deallocate( | |
980 | pointer, size, this_handler->handler_); | |
981 | } | |
982 | ||
983 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
984 | typename CompletionCondition, typename ReadHandler> | |
985 | inline bool asio_handler_is_continuation( | |
986 | read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, | |
987 | CompletionCondition, ReadHandler>* this_handler) | |
988 | { | |
989 | return this_handler->start_ == 0 ? true | |
990 | : boost_asio_handler_cont_helpers::is_continuation( | |
991 | this_handler->handler_); | |
992 | } | |
993 | ||
994 | template <typename Function, typename AsyncReadStream, | |
995 | typename DynamicBuffer_v2, typename CompletionCondition, | |
996 | typename ReadHandler> | |
997 | inline void asio_handler_invoke(Function& function, | |
998 | read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, | |
999 | CompletionCondition, ReadHandler>* this_handler) | |
1000 | { | |
1001 | boost_asio_handler_invoke_helpers::invoke( | |
1002 | function, this_handler->handler_); | |
1003 | } | |
1004 | ||
1005 | template <typename Function, typename AsyncReadStream, | |
1006 | typename DynamicBuffer_v2, typename CompletionCondition, | |
1007 | typename ReadHandler> | |
1008 | inline void asio_handler_invoke(const Function& function, | |
1009 | read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, | |
1010 | CompletionCondition, ReadHandler>* this_handler) | |
1011 | { | |
1012 | boost_asio_handler_invoke_helpers::invoke( | |
1013 | function, this_handler->handler_); | |
1014 | } | |
1015 | ||
1016 | template <typename AsyncReadStream> | |
1017 | class initiate_async_read_dynbuf_v2 | |
1018 | { | |
1019 | public: | |
1020 | typedef typename AsyncReadStream::executor_type executor_type; | |
1021 | ||
1022 | explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream) | |
1023 | : stream_(stream) | |
1024 | { | |
1025 | } | |
1026 | ||
1027 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
1028 | { | |
1029 | return stream_.get_executor(); | |
1030 | } | |
1031 | ||
1032 | template <typename ReadHandler, typename DynamicBuffer_v2, | |
1033 | typename CompletionCondition> | |
1034 | void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
1035 | BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, | |
1036 | BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const | |
1037 | { | |
1038 | // If you get an error on the following line it means that your handler | |
1039 | // does not meet the documented type requirements for a ReadHandler. | |
1040 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; | |
1041 | ||
1042 | non_const_lvalue<ReadHandler> handler2(handler); | |
1043 | non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); | |
1044 | read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type, | |
1045 | CompletionCondition, typename decay<ReadHandler>::type>( | |
1046 | stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), | |
1047 | completion_cond2.value, handler2.value)( | |
1048 | boost::system::error_code(), 0, 1); | |
1049 | } | |
1050 | ||
1051 | private: | |
1052 | AsyncReadStream& stream_; | |
1053 | }; | |
1054 | } // namespace detail | |
1055 | ||
1056 | #if !defined(GENERATING_DOCUMENTATION) | |
1057 | ||
1058 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
1059 | typename CompletionCondition, typename ReadHandler, typename Allocator> | |
1060 | struct associated_allocator< | |
1061 | detail::read_dynbuf_v2_op<AsyncReadStream, | |
1062 | DynamicBuffer_v2, CompletionCondition, ReadHandler>, | |
1063 | Allocator> | |
1064 | { | |
1065 | typedef typename associated_allocator<ReadHandler, Allocator>::type type; | |
1066 | ||
1067 | static type get( | |
1068 | const detail::read_dynbuf_v2_op<AsyncReadStream, | |
1069 | DynamicBuffer_v2, CompletionCondition, ReadHandler>& h, | |
1070 | const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT | |
1071 | { | |
1072 | return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); | |
1073 | } | |
1074 | }; | |
1075 | ||
1076 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
1077 | typename CompletionCondition, typename ReadHandler, typename Executor> | |
1078 | struct associated_executor< | |
1079 | detail::read_dynbuf_v2_op<AsyncReadStream, | |
1080 | DynamicBuffer_v2, CompletionCondition, ReadHandler>, | |
1081 | Executor> | |
1082 | { | |
1083 | typedef typename associated_executor<ReadHandler, Executor>::type type; | |
1084 | ||
1085 | static type get( | |
1086 | const detail::read_dynbuf_v2_op<AsyncReadStream, | |
1087 | DynamicBuffer_v2, CompletionCondition, ReadHandler>& h, | |
1088 | const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT | |
1089 | { | |
1090 | return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); | |
1091 | } | |
1092 | }; | |
1093 | ||
1094 | #endif // !defined(GENERATING_DOCUMENTATION) | |
1095 | ||
1096 | template <typename AsyncReadStream, typename DynamicBuffer_v2, | |
1097 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
1098 | std::size_t)) ReadHandler> | |
1099 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
1100 | void (boost::system::error_code, std::size_t)) | |
1101 | async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, | |
1102 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
1103 | typename enable_if< | |
1104 | is_dynamic_buffer_v2<DynamicBuffer_v2>::value | |
1105 | >::type*) | |
1106 | { | |
1107 | return async_read(s, | |
1108 | BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), | |
1109 | transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); | |
1110 | } | |
1111 | ||
1112 | template <typename AsyncReadStream, | |
1113 | typename DynamicBuffer_v2, typename CompletionCondition, | |
1114 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
1115 | std::size_t)) ReadHandler> | |
1116 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, | |
1117 | void (boost::system::error_code, std::size_t)) | |
1118 | async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, | |
1119 | CompletionCondition completion_condition, | |
1120 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler, | |
1121 | typename enable_if< | |
1122 | is_dynamic_buffer_v2<DynamicBuffer_v2>::value | |
1123 | >::type*) | |
1124 | { | |
92f5a8d4 TL |
1125 | return async_initiate<ReadHandler, |
1126 | void (boost::system::error_code, std::size_t)>( | |
1127 | detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s), | |
1128 | handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), | |
1129 | BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); | |
1130 | } | |
b32b8144 FG |
1131 | |
1132 | } // namespace asio | |
1133 | } // namespace boost | |
1134 | ||
1135 | #include <boost/asio/detail/pop_options.hpp> | |
1136 | ||
1137 | #endif // BOOST_ASIO_IMPL_READ_HPP |