]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // impl/write.hpp | |
3 | // ~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2003-2016 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 |