]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/impl/buffered_write_stream.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / impl / buffered_write_stream.hpp
1 //
2 // impl/buffered_write_stream.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2022 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_BUFFERED_WRITE_STREAM_HPP
12 #define BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_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/associator.hpp>
19 #include <boost/asio/detail/handler_alloc_helpers.hpp>
20 #include <boost/asio/detail/handler_cont_helpers.hpp>
21 #include <boost/asio/detail/handler_invoke_helpers.hpp>
22 #include <boost/asio/detail/handler_type_requirements.hpp>
23 #include <boost/asio/detail/non_const_lvalue.hpp>
24
25 #include <boost/asio/detail/push_options.hpp>
26
27 namespace boost {
28 namespace asio {
29
30 template <typename Stream>
31 std::size_t buffered_write_stream<Stream>::flush()
32 {
33 std::size_t bytes_written = write(next_layer_,
34 buffer(storage_.data(), storage_.size()));
35 storage_.consume(bytes_written);
36 return bytes_written;
37 }
38
39 template <typename Stream>
40 std::size_t buffered_write_stream<Stream>::flush(boost::system::error_code& ec)
41 {
42 std::size_t bytes_written = write(next_layer_,
43 buffer(storage_.data(), storage_.size()),
44 transfer_all(), ec);
45 storage_.consume(bytes_written);
46 return bytes_written;
47 }
48
49 namespace detail
50 {
51 template <typename WriteHandler>
52 class buffered_flush_handler
53 {
54 public:
55 buffered_flush_handler(detail::buffered_stream_storage& storage,
56 WriteHandler& handler)
57 : storage_(storage),
58 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
59 {
60 }
61
62 #if defined(BOOST_ASIO_HAS_MOVE)
63 buffered_flush_handler(const buffered_flush_handler& other)
64 : storage_(other.storage_),
65 handler_(other.handler_)
66 {
67 }
68
69 buffered_flush_handler(buffered_flush_handler&& other)
70 : storage_(other.storage_),
71 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
72 {
73 }
74 #endif // defined(BOOST_ASIO_HAS_MOVE)
75
76 void operator()(const boost::system::error_code& ec,
77 const std::size_t bytes_written)
78 {
79 storage_.consume(bytes_written);
80 BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_written);
81 }
82
83 //private:
84 detail::buffered_stream_storage& storage_;
85 WriteHandler handler_;
86 };
87
88 template <typename WriteHandler>
89 inline asio_handler_allocate_is_deprecated
90 asio_handler_allocate(std::size_t size,
91 buffered_flush_handler<WriteHandler>* this_handler)
92 {
93 #if defined(BOOST_ASIO_NO_DEPRECATED)
94 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
95 return asio_handler_allocate_is_no_longer_used();
96 #else // defined(BOOST_ASIO_NO_DEPRECATED)
97 return boost_asio_handler_alloc_helpers::allocate(
98 size, this_handler->handler_);
99 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
100 }
101
102 template <typename WriteHandler>
103 inline asio_handler_deallocate_is_deprecated
104 asio_handler_deallocate(void* pointer, std::size_t size,
105 buffered_flush_handler<WriteHandler>* this_handler)
106 {
107 boost_asio_handler_alloc_helpers::deallocate(
108 pointer, size, this_handler->handler_);
109 #if defined(BOOST_ASIO_NO_DEPRECATED)
110 return asio_handler_deallocate_is_no_longer_used();
111 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
112 }
113
114 template <typename WriteHandler>
115 inline bool asio_handler_is_continuation(
116 buffered_flush_handler<WriteHandler>* this_handler)
117 {
118 return boost_asio_handler_cont_helpers::is_continuation(
119 this_handler->handler_);
120 }
121
122 template <typename Function, typename WriteHandler>
123 inline asio_handler_invoke_is_deprecated
124 asio_handler_invoke(Function& function,
125 buffered_flush_handler<WriteHandler>* this_handler)
126 {
127 boost_asio_handler_invoke_helpers::invoke(
128 function, this_handler->handler_);
129 #if defined(BOOST_ASIO_NO_DEPRECATED)
130 return asio_handler_invoke_is_no_longer_used();
131 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
132 }
133
134 template <typename Function, typename WriteHandler>
135 inline asio_handler_invoke_is_deprecated
136 asio_handler_invoke(const Function& function,
137 buffered_flush_handler<WriteHandler>* this_handler)
138 {
139 boost_asio_handler_invoke_helpers::invoke(
140 function, this_handler->handler_);
141 #if defined(BOOST_ASIO_NO_DEPRECATED)
142 return asio_handler_invoke_is_no_longer_used();
143 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
144 }
145
146 template <typename Stream>
147 class initiate_async_buffered_flush
148 {
149 public:
150 typedef typename remove_reference<
151 Stream>::type::lowest_layer_type::executor_type executor_type;
152
153 explicit initiate_async_buffered_flush(
154 typename remove_reference<Stream>::type& next_layer)
155 : next_layer_(next_layer)
156 {
157 }
158
159 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
160 {
161 return next_layer_.lowest_layer().get_executor();
162 }
163
164 template <typename WriteHandler>
165 void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
166 buffered_stream_storage* storage) const
167 {
168 // If you get an error on the following line it means that your handler
169 // does not meet the documented type requirements for a WriteHandler.
170 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
171
172 non_const_lvalue<WriteHandler> handler2(handler);
173 async_write(next_layer_, buffer(storage->data(), storage->size()),
174 buffered_flush_handler<typename decay<WriteHandler>::type>(
175 *storage, handler2.value));
176 }
177
178 private:
179 typename remove_reference<Stream>::type& next_layer_;
180 };
181 } // namespace detail
182
183 #if !defined(GENERATING_DOCUMENTATION)
184
185 template <template <typename, typename> class Associator,
186 typename WriteHandler, typename DefaultCandidate>
187 struct associator<Associator,
188 detail::buffered_flush_handler<WriteHandler>,
189 DefaultCandidate>
190 : Associator<WriteHandler, DefaultCandidate>
191 {
192 static typename Associator<WriteHandler, DefaultCandidate>::type get(
193 const detail::buffered_flush_handler<WriteHandler>& h,
194 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
195 {
196 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
197 }
198 };
199
200 #endif // !defined(GENERATING_DOCUMENTATION)
201
202 template <typename Stream>
203 template <
204 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
205 std::size_t)) WriteHandler>
206 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
207 void (boost::system::error_code, std::size_t))
208 buffered_write_stream<Stream>::async_flush(
209 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
210 {
211 return async_initiate<WriteHandler,
212 void (boost::system::error_code, std::size_t)>(
213 detail::initiate_async_buffered_flush<Stream>(next_layer_),
214 handler, &storage_);
215 }
216
217 template <typename Stream>
218 template <typename ConstBufferSequence>
219 std::size_t buffered_write_stream<Stream>::write_some(
220 const ConstBufferSequence& buffers)
221 {
222 using boost::asio::buffer_size;
223 if (buffer_size(buffers) == 0)
224 return 0;
225
226 if (storage_.size() == storage_.capacity())
227 this->flush();
228
229 return this->copy(buffers);
230 }
231
232 template <typename Stream>
233 template <typename ConstBufferSequence>
234 std::size_t buffered_write_stream<Stream>::write_some(
235 const ConstBufferSequence& buffers, boost::system::error_code& ec)
236 {
237 ec = boost::system::error_code();
238
239 using boost::asio::buffer_size;
240 if (buffer_size(buffers) == 0)
241 return 0;
242
243 if (storage_.size() == storage_.capacity() && !flush(ec))
244 return 0;
245
246 return this->copy(buffers);
247 }
248
249 namespace detail
250 {
251 template <typename ConstBufferSequence, typename WriteHandler>
252 class buffered_write_some_handler
253 {
254 public:
255 buffered_write_some_handler(detail::buffered_stream_storage& storage,
256 const ConstBufferSequence& buffers, WriteHandler& handler)
257 : storage_(storage),
258 buffers_(buffers),
259 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
260 {
261 }
262
263 #if defined(BOOST_ASIO_HAS_MOVE)
264 buffered_write_some_handler(const buffered_write_some_handler& other)
265 : storage_(other.storage_),
266 buffers_(other.buffers_),
267 handler_(other.handler_)
268 {
269 }
270
271 buffered_write_some_handler(buffered_write_some_handler&& other)
272 : storage_(other.storage_),
273 buffers_(other.buffers_),
274 handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
275 {
276 }
277 #endif // defined(BOOST_ASIO_HAS_MOVE)
278
279 void operator()(const boost::system::error_code& ec, std::size_t)
280 {
281 if (ec)
282 {
283 const std::size_t length = 0;
284 BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, length);
285 }
286 else
287 {
288 using boost::asio::buffer_size;
289 std::size_t orig_size = storage_.size();
290 std::size_t space_avail = storage_.capacity() - orig_size;
291 std::size_t bytes_avail = buffer_size(buffers_);
292 std::size_t length = bytes_avail < space_avail
293 ? bytes_avail : space_avail;
294 storage_.resize(orig_size + length);
295 const std::size_t bytes_copied = boost::asio::buffer_copy(
296 storage_.data() + orig_size, buffers_, length);
297 BOOST_ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_copied);
298 }
299 }
300
301 //private:
302 detail::buffered_stream_storage& storage_;
303 ConstBufferSequence buffers_;
304 WriteHandler handler_;
305 };
306
307 template <typename ConstBufferSequence, typename WriteHandler>
308 inline asio_handler_allocate_is_deprecated
309 asio_handler_allocate(std::size_t size,
310 buffered_write_some_handler<
311 ConstBufferSequence, WriteHandler>* this_handler)
312 {
313 #if defined(BOOST_ASIO_NO_DEPRECATED)
314 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
315 return asio_handler_allocate_is_no_longer_used();
316 #else // defined(BOOST_ASIO_NO_DEPRECATED)
317 return boost_asio_handler_alloc_helpers::allocate(
318 size, this_handler->handler_);
319 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
320 }
321
322 template <typename ConstBufferSequence, typename WriteHandler>
323 inline asio_handler_deallocate_is_deprecated
324 asio_handler_deallocate(void* pointer, std::size_t size,
325 buffered_write_some_handler<
326 ConstBufferSequence, WriteHandler>* this_handler)
327 {
328 boost_asio_handler_alloc_helpers::deallocate(
329 pointer, size, this_handler->handler_);
330 #if defined(BOOST_ASIO_NO_DEPRECATED)
331 return asio_handler_deallocate_is_no_longer_used();
332 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
333 }
334
335 template <typename ConstBufferSequence, typename WriteHandler>
336 inline bool asio_handler_is_continuation(
337 buffered_write_some_handler<
338 ConstBufferSequence, WriteHandler>* this_handler)
339 {
340 return boost_asio_handler_cont_helpers::is_continuation(
341 this_handler->handler_);
342 }
343
344 template <typename Function, typename ConstBufferSequence,
345 typename WriteHandler>
346 inline asio_handler_invoke_is_deprecated
347 asio_handler_invoke(Function& function,
348 buffered_write_some_handler<
349 ConstBufferSequence, WriteHandler>* this_handler)
350 {
351 boost_asio_handler_invoke_helpers::invoke(
352 function, this_handler->handler_);
353 #if defined(BOOST_ASIO_NO_DEPRECATED)
354 return asio_handler_invoke_is_no_longer_used();
355 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
356 }
357
358 template <typename Function, typename ConstBufferSequence,
359 typename WriteHandler>
360 inline asio_handler_invoke_is_deprecated
361 asio_handler_invoke(const Function& function,
362 buffered_write_some_handler<
363 ConstBufferSequence, WriteHandler>* this_handler)
364 {
365 boost_asio_handler_invoke_helpers::invoke(
366 function, this_handler->handler_);
367 #if defined(BOOST_ASIO_NO_DEPRECATED)
368 return asio_handler_invoke_is_no_longer_used();
369 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
370 }
371
372 template <typename Stream>
373 class initiate_async_buffered_write_some
374 {
375 public:
376 typedef typename remove_reference<
377 Stream>::type::lowest_layer_type::executor_type executor_type;
378
379 explicit initiate_async_buffered_write_some(
380 typename remove_reference<Stream>::type& next_layer)
381 : next_layer_(next_layer)
382 {
383 }
384
385 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
386 {
387 return next_layer_.lowest_layer().get_executor();
388 }
389
390 template <typename WriteHandler, typename ConstBufferSequence>
391 void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
392 buffered_stream_storage* storage,
393 const ConstBufferSequence& buffers) const
394 {
395 // If you get an error on the following line it means that your handler
396 // does not meet the documented type requirements for a WriteHandler.
397 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
398
399 using boost::asio::buffer_size;
400 non_const_lvalue<WriteHandler> handler2(handler);
401 if (buffer_size(buffers) == 0 || storage->size() < storage->capacity())
402 {
403 next_layer_.async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
404 buffered_write_some_handler<ConstBufferSequence,
405 typename decay<WriteHandler>::type>(
406 *storage, buffers, handler2.value));
407 }
408 else
409 {
410 initiate_async_buffered_flush<Stream>(this->next_layer_)(
411 buffered_write_some_handler<ConstBufferSequence,
412 typename decay<WriteHandler>::type>(
413 *storage, buffers, handler2.value),
414 storage);
415 }
416 }
417
418 private:
419 typename remove_reference<Stream>::type& next_layer_;
420 };
421 } // namespace detail
422
423 #if !defined(GENERATING_DOCUMENTATION)
424
425 template <template <typename, typename> class Associator,
426 typename ConstBufferSequence, typename WriteHandler,
427 typename DefaultCandidate>
428 struct associator<Associator,
429 detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
430 DefaultCandidate>
431 : Associator<WriteHandler, DefaultCandidate>
432 {
433 static typename Associator<WriteHandler, DefaultCandidate>::type get(
434 const detail::buffered_write_some_handler<
435 ConstBufferSequence, WriteHandler>& h,
436 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
437 {
438 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
439 }
440 };
441
442 #endif // !defined(GENERATING_DOCUMENTATION)
443
444 template <typename Stream>
445 template <typename ConstBufferSequence,
446 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
447 std::size_t)) WriteHandler>
448 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
449 void (boost::system::error_code, std::size_t))
450 buffered_write_stream<Stream>::async_write_some(
451 const ConstBufferSequence& buffers,
452 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
453 {
454 return async_initiate<WriteHandler,
455 void (boost::system::error_code, std::size_t)>(
456 detail::initiate_async_buffered_write_some<Stream>(next_layer_),
457 handler, &storage_, buffers);
458 }
459
460 template <typename Stream>
461 template <typename ConstBufferSequence>
462 std::size_t buffered_write_stream<Stream>::copy(
463 const ConstBufferSequence& buffers)
464 {
465 using boost::asio::buffer_size;
466 std::size_t orig_size = storage_.size();
467 std::size_t space_avail = storage_.capacity() - orig_size;
468 std::size_t bytes_avail = buffer_size(buffers);
469 std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;
470 storage_.resize(orig_size + length);
471 return boost::asio::buffer_copy(
472 storage_.data() + orig_size, buffers, length);
473 }
474
475 } // namespace asio
476 } // namespace boost
477
478 #include <boost/asio/detail/pop_options.hpp>
479
480 #endif // BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP