1 | // |
2 | // impl/write.hpp |
3 | // ~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
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_WRITE_HPP |
12 | #define BOOST_ASIO_IMPL_WRITE_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/buffer.hpp> |
19 | #include <boost/asio/completion_condition.hpp> |
20 | #include <boost/asio/detail/array_fwd.hpp> |
21 | #include <boost/asio/detail/base_from_completion_cond.hpp> |
22 | #include <boost/asio/detail/bind_handler.hpp> |
23 | #include <boost/asio/detail/consuming_buffers.hpp> |
24 | #include <boost/asio/detail/dependent_type.hpp> |
25 | #include <boost/asio/detail/handler_alloc_helpers.hpp> |
26 | #include <boost/asio/detail/handler_cont_helpers.hpp> |
27 | #include <boost/asio/detail/handler_invoke_helpers.hpp> |
28 | #include <boost/asio/detail/handler_type_requirements.hpp> |
29 | #include <boost/asio/detail/throw_error.hpp> |
30 | |
31 | #include <boost/asio/detail/push_options.hpp> |
32 | |
33 | namespace boost { |
34 | namespace asio { |
35 | |
36 | template <typename SyncWriteStream, typename ConstBufferSequence, |
37 | typename CompletionCondition> |
38 | std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, |
39 | CompletionCondition completion_condition, boost::system::error_code& ec) |
40 | { |
41 | ec = boost::system::error_code(); |
42 | boost::asio::detail::consuming_buffers< |
43 | const_buffer, ConstBufferSequence> tmp(buffers); |
44 | std::size_t total_transferred = 0; |
45 | tmp.prepare(detail::adapt_completion_condition_result( |
46 | completion_condition(ec, total_transferred))); |
47 | while (tmp.begin() != tmp.end()) |
48 | { |
49 | std::size_t bytes_transferred = s.write_some(tmp, ec); |
50 | tmp.consume(bytes_transferred); |
51 | total_transferred += bytes_transferred; |
52 | tmp.prepare(detail::adapt_completion_condition_result( |
53 | completion_condition(ec, total_transferred))); |
54 | } |
55 | return total_transferred; |
56 | } |
57 | |
58 | template <typename SyncWriteStream, typename ConstBufferSequence> |
59 | inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers) |
60 | { |
61 | boost::system::error_code ec; |
62 | std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec); |
63 | boost::asio::detail::throw_error(ec, "write" ); |
64 | return bytes_transferred; |
65 | } |
66 | |
67 | template <typename SyncWriteStream, typename ConstBufferSequence> |
68 | inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, |
69 | boost::system::error_code& ec) |
70 | { |
71 | return write(s, buffers, transfer_all(), ec); |
72 | } |
73 | |
74 | template <typename SyncWriteStream, typename ConstBufferSequence, |
75 | typename CompletionCondition> |
76 | inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, |
77 | CompletionCondition completion_condition) |
78 | { |
79 | boost::system::error_code ec; |
80 | std::size_t bytes_transferred = write(s, buffers, completion_condition, ec); |
81 | boost::asio::detail::throw_error(ec, "write" ); |
82 | return bytes_transferred; |
83 | } |
84 | |
85 | #if !defined(BOOST_ASIO_NO_IOSTREAM) |
86 | |
87 | template <typename SyncWriteStream, typename Allocator, |
88 | typename CompletionCondition> |
89 | std::size_t write(SyncWriteStream& s, |
90 | boost::asio::basic_streambuf<Allocator>& b, |
91 | CompletionCondition completion_condition, boost::system::error_code& ec) |
92 | { |
93 | std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec); |
94 | b.consume(bytes_transferred); |
95 | return bytes_transferred; |
96 | } |
97 | |
98 | template <typename SyncWriteStream, typename Allocator> |
99 | inline std::size_t write(SyncWriteStream& s, |
100 | boost::asio::basic_streambuf<Allocator>& b) |
101 | { |
102 | boost::system::error_code ec; |
103 | std::size_t bytes_transferred = write(s, b, transfer_all(), ec); |
104 | boost::asio::detail::throw_error(ec, "write" ); |
105 | return bytes_transferred; |
106 | } |
107 | |
108 | template <typename SyncWriteStream, typename Allocator> |
109 | inline std::size_t write(SyncWriteStream& s, |
110 | boost::asio::basic_streambuf<Allocator>& b, |
111 | boost::system::error_code& ec) |
112 | { |
113 | return write(s, b, transfer_all(), ec); |
114 | } |
115 | |
116 | template <typename SyncWriteStream, typename Allocator, |
117 | typename CompletionCondition> |
118 | inline std::size_t write(SyncWriteStream& s, |
119 | boost::asio::basic_streambuf<Allocator>& b, |
120 | CompletionCondition completion_condition) |
121 | { |
122 | boost::system::error_code ec; |
123 | std::size_t bytes_transferred = write(s, b, completion_condition, ec); |
124 | boost::asio::detail::throw_error(ec, "write" ); |
125 | return bytes_transferred; |
126 | } |
127 | |
128 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) |
129 | |
130 | namespace detail |
131 | { |
132 | template <typename AsyncWriteStream, typename ConstBufferSequence, |
133 | typename CompletionCondition, typename WriteHandler> |
134 | class write_op |
135 | : detail::base_from_completion_cond<CompletionCondition> |
136 | { |
137 | public: |
138 | write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, |
139 | CompletionCondition completion_condition, WriteHandler& handler) |
140 | : detail::base_from_completion_cond< |
141 | CompletionCondition>(completion_condition), |
142 | stream_(stream), |
143 | buffers_(buffers), |
144 | start_(0), |
145 | total_transferred_(0), |
146 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
147 | { |
148 | } |
149 | |
150 | #if defined(BOOST_ASIO_HAS_MOVE) |
151 | write_op(const write_op& other) |
152 | : detail::base_from_completion_cond<CompletionCondition>(other), |
153 | stream_(other.stream_), |
154 | buffers_(other.buffers_), |
155 | start_(other.start_), |
156 | total_transferred_(other.total_transferred_), |
157 | handler_(other.handler_) |
158 | { |
159 | } |
160 | |
161 | write_op(write_op&& other) |
162 | : detail::base_from_completion_cond<CompletionCondition>(other), |
163 | stream_(other.stream_), |
164 | buffers_(other.buffers_), |
165 | start_(other.start_), |
166 | total_transferred_(other.total_transferred_), |
167 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
168 | { |
169 | } |
170 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
171 | |
172 | void operator()(const boost::system::error_code& ec, |
173 | std::size_t bytes_transferred, int start = 0) |
174 | { |
175 | switch (start_ = start) |
176 | { |
177 | case 1: |
178 | buffers_.prepare(this->check_for_completion(ec, total_transferred_)); |
179 | for (;;) |
180 | { |
181 | stream_.async_write_some(buffers_, |
182 | BOOST_ASIO_MOVE_CAST(write_op)(*this)); |
183 | return; default: |
184 | total_transferred_ += bytes_transferred; |
185 | buffers_.consume(bytes_transferred); |
186 | buffers_.prepare(this->check_for_completion(ec, total_transferred_)); |
187 | if ((!ec && bytes_transferred == 0) |
188 | || buffers_.begin() == buffers_.end()) |
189 | break; |
190 | } |
191 | |
192 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
193 | } |
194 | } |
195 | |
196 | //private: |
197 | AsyncWriteStream& stream_; |
198 | boost::asio::detail::consuming_buffers< |
199 | const_buffer, ConstBufferSequence> buffers_; |
200 | int start_; |
201 | std::size_t total_transferred_; |
202 | WriteHandler handler_; |
203 | }; |
204 | |
205 | template <typename AsyncWriteStream, |
206 | typename CompletionCondition, typename WriteHandler> |
207 | class write_op<AsyncWriteStream, boost::asio::mutable_buffers_1, |
208 | CompletionCondition, WriteHandler> |
209 | : detail::base_from_completion_cond<CompletionCondition> |
210 | { |
211 | public: |
212 | write_op(AsyncWriteStream& stream, |
213 | const boost::asio::mutable_buffers_1& buffers, |
214 | CompletionCondition completion_condition, |
215 | WriteHandler& handler) |
216 | : detail::base_from_completion_cond< |
217 | CompletionCondition>(completion_condition), |
218 | stream_(stream), |
219 | buffer_(buffers), |
220 | start_(0), |
221 | total_transferred_(0), |
222 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
223 | { |
224 | } |
225 | |
226 | #if defined(BOOST_ASIO_HAS_MOVE) |
227 | write_op(const write_op& other) |
228 | : detail::base_from_completion_cond<CompletionCondition>(other), |
229 | stream_(other.stream_), |
230 | buffer_(other.buffer_), |
231 | start_(other.start_), |
232 | total_transferred_(other.total_transferred_), |
233 | handler_(other.handler_) |
234 | { |
235 | } |
236 | |
237 | write_op(write_op&& other) |
238 | : detail::base_from_completion_cond<CompletionCondition>(other), |
239 | stream_(other.stream_), |
240 | buffer_(other.buffer_), |
241 | start_(other.start_), |
242 | total_transferred_(other.total_transferred_), |
243 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
244 | { |
245 | } |
246 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
247 | |
248 | void operator()(const boost::system::error_code& ec, |
249 | std::size_t bytes_transferred, int start = 0) |
250 | { |
251 | std::size_t n = 0; |
252 | switch (start_ = start) |
253 | { |
254 | case 1: |
255 | n = this->check_for_completion(ec, total_transferred_); |
256 | for (;;) |
257 | { |
258 | stream_.async_write_some( |
259 | boost::asio::buffer(buffer_ + total_transferred_, n), |
260 | BOOST_ASIO_MOVE_CAST(write_op)(*this)); |
261 | return; default: |
262 | total_transferred_ += bytes_transferred; |
263 | if ((!ec && bytes_transferred == 0) |
264 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
265 | || total_transferred_ == boost::asio::buffer_size(buffer_)) |
266 | break; |
267 | } |
268 | |
269 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
270 | } |
271 | } |
272 | |
273 | //private: |
274 | AsyncWriteStream& stream_; |
275 | boost::asio::mutable_buffer buffer_; |
276 | int start_; |
277 | std::size_t total_transferred_; |
278 | WriteHandler handler_; |
279 | }; |
280 | |
281 | template <typename AsyncWriteStream, |
282 | typename CompletionCondition, typename WriteHandler> |
283 | class write_op<AsyncWriteStream, boost::asio::const_buffers_1, |
284 | CompletionCondition, WriteHandler> |
285 | : detail::base_from_completion_cond<CompletionCondition> |
286 | { |
287 | public: |
288 | write_op(AsyncWriteStream& stream, |
289 | const boost::asio::const_buffers_1& buffers, |
290 | CompletionCondition completion_condition, |
291 | WriteHandler& handler) |
292 | : detail::base_from_completion_cond< |
293 | CompletionCondition>(completion_condition), |
294 | stream_(stream), |
295 | buffer_(buffers), |
296 | start_(0), |
297 | total_transferred_(0), |
298 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
299 | { |
300 | } |
301 | |
302 | #if defined(BOOST_ASIO_HAS_MOVE) |
303 | write_op(const write_op& other) |
304 | : detail::base_from_completion_cond<CompletionCondition>(other), |
305 | stream_(other.stream_), |
306 | buffer_(other.buffer_), |
307 | start_(other.start_), |
308 | total_transferred_(other.total_transferred_), |
309 | handler_(other.handler_) |
310 | { |
311 | } |
312 | |
313 | write_op(write_op&& other) |
314 | : detail::base_from_completion_cond<CompletionCondition>(other), |
315 | stream_(other.stream_), |
316 | buffer_(other.buffer_), |
317 | start_(other.start_), |
318 | total_transferred_(other.total_transferred_), |
319 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
320 | { |
321 | } |
322 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
323 | |
324 | void operator()(const boost::system::error_code& ec, |
325 | std::size_t bytes_transferred, int start = 0) |
326 | { |
327 | std::size_t n = 0; |
328 | switch (start_ = start) |
329 | { |
330 | case 1: |
331 | n = this->check_for_completion(ec, total_transferred_); |
332 | for (;;) |
333 | { |
334 | stream_.async_write_some( |
335 | boost::asio::buffer(buffer_ + total_transferred_, n), |
336 | BOOST_ASIO_MOVE_CAST(write_op)(*this)); |
337 | return; default: |
338 | total_transferred_ += bytes_transferred; |
339 | if ((!ec && bytes_transferred == 0) |
340 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
341 | || total_transferred_ == boost::asio::buffer_size(buffer_)) |
342 | break; |
343 | } |
344 | |
345 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
346 | } |
347 | } |
348 | |
349 | //private: |
350 | AsyncWriteStream& stream_; |
351 | boost::asio::const_buffer buffer_; |
352 | int start_; |
353 | std::size_t total_transferred_; |
354 | WriteHandler handler_; |
355 | }; |
356 | |
357 | template <typename AsyncWriteStream, typename Elem, |
358 | typename CompletionCondition, typename WriteHandler> |
359 | class write_op<AsyncWriteStream, boost::array<Elem, 2>, |
360 | CompletionCondition, WriteHandler> |
361 | : detail::base_from_completion_cond<CompletionCondition> |
362 | { |
363 | public: |
364 | write_op(AsyncWriteStream& stream, const boost::array<Elem, 2>& buffers, |
365 | CompletionCondition completion_condition, WriteHandler& handler) |
366 | : detail::base_from_completion_cond< |
367 | CompletionCondition>(completion_condition), |
368 | stream_(stream), |
369 | buffers_(buffers), |
370 | start_(0), |
371 | total_transferred_(0), |
372 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
373 | { |
374 | } |
375 | |
376 | #if defined(BOOST_ASIO_HAS_MOVE) |
377 | write_op(const write_op& other) |
378 | : detail::base_from_completion_cond<CompletionCondition>(other), |
379 | stream_(other.stream_), |
380 | buffers_(other.buffers_), |
381 | start_(other.start_), |
382 | total_transferred_(other.total_transferred_), |
383 | handler_(other.handler_) |
384 | { |
385 | } |
386 | |
387 | write_op(write_op&& other) |
388 | : detail::base_from_completion_cond<CompletionCondition>(other), |
389 | stream_(other.stream_), |
390 | buffers_(other.buffers_), |
391 | start_(other.start_), |
392 | total_transferred_(other.total_transferred_), |
393 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
394 | { |
395 | } |
396 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
397 | |
398 | void operator()(const boost::system::error_code& ec, |
399 | std::size_t bytes_transferred, int start = 0) |
400 | { |
401 | typename boost::asio::detail::dependent_type<Elem, |
402 | boost::array<boost::asio::const_buffer, 2> >::type bufs = {{ |
403 | boost::asio::const_buffer(buffers_[0]), |
404 | boost::asio::const_buffer(buffers_[1]) }}; |
405 | std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]); |
406 | std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]); |
407 | std::size_t n = 0; |
408 | switch (start_ = start) |
409 | { |
410 | case 1: |
411 | n = this->check_for_completion(ec, total_transferred_); |
412 | for (;;) |
413 | { |
414 | bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n); |
415 | bufs[1] = boost::asio::buffer( |
416 | bufs[1] + (total_transferred_ < buffer_size0 |
417 | ? 0 : total_transferred_ - buffer_size0), |
418 | n - boost::asio::buffer_size(bufs[0])); |
419 | stream_.async_write_some(bufs, BOOST_ASIO_MOVE_CAST(write_op)(*this)); |
420 | return; default: |
421 | total_transferred_ += bytes_transferred; |
422 | if ((!ec && bytes_transferred == 0) |
423 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
424 | || total_transferred_ == buffer_size0 + buffer_size1) |
425 | break; |
426 | } |
427 | |
428 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
429 | } |
430 | } |
431 | |
432 | //private: |
433 | AsyncWriteStream& stream_; |
434 | boost::array<Elem, 2> buffers_; |
435 | int start_; |
436 | std::size_t total_transferred_; |
437 | WriteHandler handler_; |
438 | }; |
439 | |
440 | #if defined(BOOST_ASIO_HAS_STD_ARRAY) |
441 | |
442 | template <typename AsyncWriteStream, typename Elem, |
443 | typename CompletionCondition, typename WriteHandler> |
444 | class write_op<AsyncWriteStream, std::array<Elem, 2>, |
445 | CompletionCondition, WriteHandler> |
446 | : detail::base_from_completion_cond<CompletionCondition> |
447 | { |
448 | public: |
449 | write_op(AsyncWriteStream& stream, const std::array<Elem, 2>& buffers, |
450 | CompletionCondition completion_condition, WriteHandler& handler) |
451 | : detail::base_from_completion_cond< |
452 | CompletionCondition>(completion_condition), |
453 | stream_(stream), |
454 | buffers_(buffers), |
455 | start_(0), |
456 | total_transferred_(0), |
457 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
458 | { |
459 | } |
460 | |
461 | #if defined(BOOST_ASIO_HAS_MOVE) |
462 | write_op(const write_op& other) |
463 | : detail::base_from_completion_cond<CompletionCondition>(other), |
464 | stream_(other.stream_), |
465 | buffers_(other.buffers_), |
466 | start_(other.start_), |
467 | total_transferred_(other.total_transferred_), |
468 | handler_(other.handler_) |
469 | { |
470 | } |
471 | |
472 | write_op(write_op&& other) |
473 | : detail::base_from_completion_cond<CompletionCondition>(other), |
474 | stream_(other.stream_), |
475 | buffers_(other.buffers_), |
476 | start_(other.start_), |
477 | total_transferred_(other.total_transferred_), |
478 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
479 | { |
480 | } |
481 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
482 | |
483 | void operator()(const boost::system::error_code& ec, |
484 | std::size_t bytes_transferred, int start = 0) |
485 | { |
486 | typename boost::asio::detail::dependent_type<Elem, |
487 | std::array<boost::asio::const_buffer, 2> >::type bufs = {{ |
488 | boost::asio::const_buffer(buffers_[0]), |
489 | boost::asio::const_buffer(buffers_[1]) }}; |
490 | std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]); |
491 | std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]); |
492 | std::size_t n = 0; |
493 | switch (start_ = start) |
494 | { |
495 | case 1: |
496 | n = this->check_for_completion(ec, total_transferred_); |
497 | for (;;) |
498 | { |
499 | bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n); |
500 | bufs[1] = boost::asio::buffer( |
501 | bufs[1] + (total_transferred_ < buffer_size0 |
502 | ? 0 : total_transferred_ - buffer_size0), |
503 | n - boost::asio::buffer_size(bufs[0])); |
504 | stream_.async_write_some(bufs, BOOST_ASIO_MOVE_CAST(write_op)(*this)); |
505 | return; default: |
506 | total_transferred_ += bytes_transferred; |
507 | if ((!ec && bytes_transferred == 0) |
508 | || (n = this->check_for_completion(ec, total_transferred_)) == 0 |
509 | || total_transferred_ == buffer_size0 + buffer_size1) |
510 | break; |
511 | } |
512 | |
513 | handler_(ec, static_cast<const std::size_t&>(total_transferred_)); |
514 | } |
515 | } |
516 | |
517 | //private: |
518 | AsyncWriteStream& stream_; |
519 | std::array<Elem, 2> buffers_; |
520 | int start_; |
521 | std::size_t total_transferred_; |
522 | WriteHandler handler_; |
523 | }; |
524 | |
525 | #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) |
526 | |
527 | template <typename AsyncWriteStream, typename ConstBufferSequence, |
528 | typename CompletionCondition, typename WriteHandler> |
529 | inline void* asio_handler_allocate(std::size_t size, |
530 | write_op<AsyncWriteStream, ConstBufferSequence, |
531 | CompletionCondition, WriteHandler>* this_handler) |
532 | { |
533 | return boost_asio_handler_alloc_helpers::allocate( |
534 | size, this_handler->handler_); |
535 | } |
536 | |
537 | template <typename AsyncWriteStream, typename ConstBufferSequence, |
538 | typename CompletionCondition, typename WriteHandler> |
539 | inline void asio_handler_deallocate(void* pointer, std::size_t size, |
540 | write_op<AsyncWriteStream, ConstBufferSequence, |
541 | CompletionCondition, WriteHandler>* this_handler) |
542 | { |
543 | boost_asio_handler_alloc_helpers::deallocate( |
544 | pointer, size, this_handler->handler_); |
545 | } |
546 | |
547 | template <typename AsyncWriteStream, typename ConstBufferSequence, |
548 | typename CompletionCondition, typename WriteHandler> |
549 | inline bool asio_handler_is_continuation( |
550 | write_op<AsyncWriteStream, ConstBufferSequence, |
551 | CompletionCondition, WriteHandler>* this_handler) |
552 | { |
553 | return this_handler->start_ == 0 ? true |
554 | : boost_asio_handler_cont_helpers::is_continuation( |
555 | this_handler->handler_); |
556 | } |
557 | |
558 | template <typename Function, typename AsyncWriteStream, |
559 | typename ConstBufferSequence, typename CompletionCondition, |
560 | typename WriteHandler> |
561 | inline void asio_handler_invoke(Function& function, |
562 | write_op<AsyncWriteStream, ConstBufferSequence, |
563 | CompletionCondition, WriteHandler>* this_handler) |
564 | { |
565 | boost_asio_handler_invoke_helpers::invoke( |
566 | function, this_handler->handler_); |
567 | } |
568 | |
569 | template <typename Function, typename AsyncWriteStream, |
570 | typename ConstBufferSequence, typename CompletionCondition, |
571 | typename WriteHandler> |
572 | inline void asio_handler_invoke(const Function& function, |
573 | write_op<AsyncWriteStream, ConstBufferSequence, |
574 | CompletionCondition, WriteHandler>* this_handler) |
575 | { |
576 | boost_asio_handler_invoke_helpers::invoke( |
577 | function, this_handler->handler_); |
578 | } |
579 | } // namespace detail |
580 | |
581 | template <typename AsyncWriteStream, typename ConstBufferSequence, |
582 | typename CompletionCondition, typename WriteHandler> |
583 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
584 | void (boost::system::error_code, std::size_t)) |
585 | async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, |
586 | CompletionCondition completion_condition, |
587 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
588 | { |
589 | // If you get an error on the following line it means that your handler does |
590 | // not meet the documented type requirements for a WriteHandler. |
591 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
592 | |
593 | detail::async_result_init< |
594 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
595 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
596 | |
597 | detail::write_op<AsyncWriteStream, ConstBufferSequence, |
598 | CompletionCondition, BOOST_ASIO_HANDLER_TYPE( |
599 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
600 | s, buffers, completion_condition, init.handler)( |
601 | boost::system::error_code(), 0, 1); |
602 | |
603 | return init.result.get(); |
604 | } |
605 | |
606 | template <typename AsyncWriteStream, typename ConstBufferSequence, |
607 | typename WriteHandler> |
608 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
609 | void (boost::system::error_code, std::size_t)) |
610 | async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, |
611 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
612 | { |
613 | // If you get an error on the following line it means that your handler does |
614 | // not meet the documented type requirements for a WriteHandler. |
615 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
616 | |
617 | detail::async_result_init< |
618 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
619 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
620 | |
621 | detail::write_op<AsyncWriteStream, ConstBufferSequence, |
622 | detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE( |
623 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
624 | s, buffers, transfer_all(), init.handler)( |
625 | boost::system::error_code(), 0, 1); |
626 | |
627 | return init.result.get(); |
628 | } |
629 | |
630 | #if !defined(BOOST_ASIO_NO_IOSTREAM) |
631 | |
632 | namespace detail |
633 | { |
634 | template <typename Allocator, typename WriteHandler> |
635 | class write_streambuf_handler |
636 | { |
637 | public: |
638 | write_streambuf_handler(boost::asio::basic_streambuf<Allocator>& streambuf, |
639 | WriteHandler& handler) |
640 | : streambuf_(streambuf), |
641 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) |
642 | { |
643 | } |
644 | |
645 | #if defined(BOOST_ASIO_HAS_MOVE) |
646 | write_streambuf_handler(const write_streambuf_handler& other) |
647 | : streambuf_(other.streambuf_), |
648 | handler_(other.handler_) |
649 | { |
650 | } |
651 | |
652 | write_streambuf_handler(write_streambuf_handler&& other) |
653 | : streambuf_(other.streambuf_), |
654 | handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) |
655 | { |
656 | } |
657 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
658 | |
659 | void operator()(const boost::system::error_code& ec, |
660 | const std::size_t bytes_transferred) |
661 | { |
662 | streambuf_.consume(bytes_transferred); |
663 | handler_(ec, bytes_transferred); |
664 | } |
665 | |
666 | //private: |
667 | boost::asio::basic_streambuf<Allocator>& streambuf_; |
668 | WriteHandler handler_; |
669 | }; |
670 | |
671 | template <typename Allocator, typename WriteHandler> |
672 | inline void* asio_handler_allocate(std::size_t size, |
673 | write_streambuf_handler<Allocator, WriteHandler>* this_handler) |
674 | { |
675 | return boost_asio_handler_alloc_helpers::allocate( |
676 | size, this_handler->handler_); |
677 | } |
678 | |
679 | template <typename Allocator, typename WriteHandler> |
680 | inline void asio_handler_deallocate(void* pointer, std::size_t size, |
681 | write_streambuf_handler<Allocator, WriteHandler>* this_handler) |
682 | { |
683 | boost_asio_handler_alloc_helpers::deallocate( |
684 | pointer, size, this_handler->handler_); |
685 | } |
686 | |
687 | template <typename Allocator, typename WriteHandler> |
688 | inline bool asio_handler_is_continuation( |
689 | write_streambuf_handler<Allocator, WriteHandler>* this_handler) |
690 | { |
691 | return boost_asio_handler_cont_helpers::is_continuation( |
692 | this_handler->handler_); |
693 | } |
694 | |
695 | template <typename Function, typename Allocator, typename WriteHandler> |
696 | inline void asio_handler_invoke(Function& function, |
697 | write_streambuf_handler<Allocator, WriteHandler>* this_handler) |
698 | { |
699 | boost_asio_handler_invoke_helpers::invoke( |
700 | function, this_handler->handler_); |
701 | } |
702 | |
703 | template <typename Function, typename Allocator, typename WriteHandler> |
704 | inline void asio_handler_invoke(const Function& function, |
705 | write_streambuf_handler<Allocator, WriteHandler>* this_handler) |
706 | { |
707 | boost_asio_handler_invoke_helpers::invoke( |
708 | function, this_handler->handler_); |
709 | } |
710 | } // namespace detail |
711 | |
712 | template <typename AsyncWriteStream, typename Allocator, |
713 | typename CompletionCondition, typename WriteHandler> |
714 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
715 | void (boost::system::error_code, std::size_t)) |
716 | async_write(AsyncWriteStream& s, |
717 | boost::asio::basic_streambuf<Allocator>& b, |
718 | CompletionCondition completion_condition, |
719 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
720 | { |
721 | // If you get an error on the following line it means that your handler does |
722 | // not meet the documented type requirements for a WriteHandler. |
723 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
724 | |
725 | detail::async_result_init< |
726 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
727 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
728 | |
729 | async_write(s, b.data(), completion_condition, |
730 | detail::write_streambuf_handler<Allocator, BOOST_ASIO_HANDLER_TYPE( |
731 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
732 | b, init.handler)); |
733 | |
734 | return init.result.get(); |
735 | } |
736 | |
737 | template <typename AsyncWriteStream, typename Allocator, typename WriteHandler> |
738 | inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
739 | void (boost::system::error_code, std::size_t)) |
740 | async_write(AsyncWriteStream& s, |
741 | boost::asio::basic_streambuf<Allocator>& b, |
742 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
743 | { |
744 | // If you get an error on the following line it means that your handler does |
745 | // not meet the documented type requirements for a WriteHandler. |
746 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
747 | |
748 | detail::async_result_init< |
749 | WriteHandler, void (boost::system::error_code, std::size_t)> init( |
750 | BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
751 | |
752 | async_write(s, b.data(), transfer_all(), |
753 | detail::write_streambuf_handler<Allocator, BOOST_ASIO_HANDLER_TYPE( |
754 | WriteHandler, void (boost::system::error_code, std::size_t))>( |
755 | b, init.handler)); |
756 | |
757 | return init.result.get(); |
758 | } |
759 | |
760 | #endif // !defined(BOOST_ASIO_NO_IOSTREAM) |
761 | |
762 | } // namespace asio |
763 | } // namespace boost |
764 | |
765 | #include <boost/asio/detail/pop_options.hpp> |
766 | |
767 | #endif // BOOST_ASIO_IMPL_WRITE_HPP |
768 | |