Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:54

0001 //
0002 // impl/buffered_write_stream.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
0012 #define BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/associator.hpp>
0019 #include <boost/asio/detail/handler_cont_helpers.hpp>
0020 #include <boost/asio/detail/handler_type_requirements.hpp>
0021 #include <boost/asio/detail/non_const_lvalue.hpp>
0022 
0023 #include <boost/asio/detail/push_options.hpp>
0024 
0025 namespace boost {
0026 namespace asio {
0027 
0028 template <typename Stream>
0029 std::size_t buffered_write_stream<Stream>::flush()
0030 {
0031   std::size_t bytes_written = write(next_layer_,
0032       buffer(storage_.data(), storage_.size()));
0033   storage_.consume(bytes_written);
0034   return bytes_written;
0035 }
0036 
0037 template <typename Stream>
0038 std::size_t buffered_write_stream<Stream>::flush(boost::system::error_code& ec)
0039 {
0040   std::size_t bytes_written = write(next_layer_,
0041       buffer(storage_.data(), storage_.size()),
0042       transfer_all(), ec);
0043   storage_.consume(bytes_written);
0044   return bytes_written;
0045 }
0046 
0047 namespace detail
0048 {
0049   template <typename WriteHandler>
0050   class buffered_flush_handler
0051   {
0052   public:
0053     buffered_flush_handler(detail::buffered_stream_storage& storage,
0054         WriteHandler& handler)
0055       : storage_(storage),
0056         handler_(static_cast<WriteHandler&&>(handler))
0057     {
0058     }
0059 
0060     buffered_flush_handler(const buffered_flush_handler& other)
0061       : storage_(other.storage_),
0062         handler_(other.handler_)
0063     {
0064     }
0065 
0066     buffered_flush_handler(buffered_flush_handler&& other)
0067       : storage_(other.storage_),
0068         handler_(static_cast<WriteHandler&&>(other.handler_))
0069     {
0070     }
0071 
0072     void operator()(const boost::system::error_code& ec,
0073         const std::size_t bytes_written)
0074     {
0075       storage_.consume(bytes_written);
0076       static_cast<WriteHandler&&>(handler_)(ec, bytes_written);
0077     }
0078 
0079   //private:
0080     detail::buffered_stream_storage& storage_;
0081     WriteHandler handler_;
0082   };
0083 
0084   template <typename WriteHandler>
0085   inline bool asio_handler_is_continuation(
0086       buffered_flush_handler<WriteHandler>* this_handler)
0087   {
0088     return boost_asio_handler_cont_helpers::is_continuation(
0089           this_handler->handler_);
0090   }
0091 
0092   template <typename Stream>
0093   class initiate_async_buffered_flush
0094   {
0095   public:
0096     typedef typename remove_reference_t<
0097       Stream>::lowest_layer_type::executor_type executor_type;
0098 
0099     explicit initiate_async_buffered_flush(
0100         remove_reference_t<Stream>& next_layer)
0101       : next_layer_(next_layer)
0102     {
0103     }
0104 
0105     executor_type get_executor() const noexcept
0106     {
0107       return next_layer_.lowest_layer().get_executor();
0108     }
0109 
0110     template <typename WriteHandler>
0111     void operator()(WriteHandler&& handler,
0112         buffered_stream_storage* storage) const
0113     {
0114       // If you get an error on the following line it means that your handler
0115       // does not meet the documented type requirements for a WriteHandler.
0116       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0117 
0118       non_const_lvalue<WriteHandler> handler2(handler);
0119       async_write(next_layer_, buffer(storage->data(), storage->size()),
0120           buffered_flush_handler<decay_t<WriteHandler>>(
0121             *storage, handler2.value));
0122     }
0123 
0124   private:
0125     remove_reference_t<Stream>& next_layer_;
0126   };
0127 } // namespace detail
0128 
0129 #if !defined(GENERATING_DOCUMENTATION)
0130 
0131 template <template <typename, typename> class Associator,
0132     typename WriteHandler, typename DefaultCandidate>
0133 struct associator<Associator,
0134     detail::buffered_flush_handler<WriteHandler>,
0135     DefaultCandidate>
0136   : Associator<WriteHandler, DefaultCandidate>
0137 {
0138   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0139       const detail::buffered_flush_handler<WriteHandler>& h) noexcept
0140   {
0141     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0142   }
0143 
0144   static auto get(const detail::buffered_flush_handler<WriteHandler>& h,
0145       const DefaultCandidate& c) noexcept
0146     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0147   {
0148     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0149   }
0150 };
0151 
0152 #endif // !defined(GENERATING_DOCUMENTATION)
0153 
0154 template <typename Stream>
0155 template <
0156     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0157       std::size_t)) WriteHandler>
0158 inline auto buffered_write_stream<Stream>::async_flush(WriteHandler&& handler)
0159   -> decltype(
0160     async_initiate<WriteHandler,
0161       void (boost::system::error_code, std::size_t)>(
0162         declval<detail::initiate_async_buffered_flush<Stream>>(),
0163         handler, declval<detail::buffered_stream_storage*>()))
0164 {
0165   return async_initiate<WriteHandler,
0166     void (boost::system::error_code, std::size_t)>(
0167       detail::initiate_async_buffered_flush<Stream>(next_layer_),
0168       handler, &storage_);
0169 }
0170 
0171 template <typename Stream>
0172 template <typename ConstBufferSequence>
0173 std::size_t buffered_write_stream<Stream>::write_some(
0174     const ConstBufferSequence& buffers)
0175 {
0176   using boost::asio::buffer_size;
0177   if (buffer_size(buffers) == 0)
0178     return 0;
0179 
0180   if (storage_.size() == storage_.capacity())
0181     this->flush();
0182 
0183   return this->copy(buffers);
0184 }
0185 
0186 template <typename Stream>
0187 template <typename ConstBufferSequence>
0188 std::size_t buffered_write_stream<Stream>::write_some(
0189     const ConstBufferSequence& buffers, boost::system::error_code& ec)
0190 {
0191   ec = boost::system::error_code();
0192 
0193   using boost::asio::buffer_size;
0194   if (buffer_size(buffers) == 0)
0195     return 0;
0196 
0197   if (storage_.size() == storage_.capacity() && !flush(ec))
0198     return 0;
0199 
0200   return this->copy(buffers);
0201 }
0202 
0203 namespace detail
0204 {
0205   template <typename ConstBufferSequence, typename WriteHandler>
0206   class buffered_write_some_handler
0207   {
0208   public:
0209     buffered_write_some_handler(detail::buffered_stream_storage& storage,
0210         const ConstBufferSequence& buffers, WriteHandler& handler)
0211       : storage_(storage),
0212         buffers_(buffers),
0213         handler_(static_cast<WriteHandler&&>(handler))
0214     {
0215     }
0216 
0217     buffered_write_some_handler(const buffered_write_some_handler& other)
0218       : storage_(other.storage_),
0219         buffers_(other.buffers_),
0220         handler_(other.handler_)
0221     {
0222     }
0223 
0224     buffered_write_some_handler(buffered_write_some_handler&& other)
0225       : storage_(other.storage_),
0226         buffers_(other.buffers_),
0227         handler_(static_cast<WriteHandler&&>(other.handler_))
0228     {
0229     }
0230 
0231     void operator()(const boost::system::error_code& ec, std::size_t)
0232     {
0233       if (ec)
0234       {
0235         const std::size_t length = 0;
0236         static_cast<WriteHandler&&>(handler_)(ec, length);
0237       }
0238       else
0239       {
0240         using boost::asio::buffer_size;
0241         std::size_t orig_size = storage_.size();
0242         std::size_t space_avail = storage_.capacity() - orig_size;
0243         std::size_t bytes_avail = buffer_size(buffers_);
0244         std::size_t length = bytes_avail < space_avail
0245           ? bytes_avail : space_avail;
0246         storage_.resize(orig_size + length);
0247         const std::size_t bytes_copied = boost::asio::buffer_copy(
0248             storage_.data() + orig_size, buffers_, length);
0249         static_cast<WriteHandler&&>(handler_)(ec, bytes_copied);
0250       }
0251     }
0252 
0253   //private:
0254     detail::buffered_stream_storage& storage_;
0255     ConstBufferSequence buffers_;
0256     WriteHandler handler_;
0257   };
0258 
0259   template <typename ConstBufferSequence, typename WriteHandler>
0260   inline bool asio_handler_is_continuation(
0261       buffered_write_some_handler<
0262         ConstBufferSequence, WriteHandler>* this_handler)
0263   {
0264     return boost_asio_handler_cont_helpers::is_continuation(
0265           this_handler->handler_);
0266   }
0267 
0268   template <typename Stream>
0269   class initiate_async_buffered_write_some
0270   {
0271   public:
0272     typedef typename remove_reference_t<
0273       Stream>::lowest_layer_type::executor_type executor_type;
0274 
0275     explicit initiate_async_buffered_write_some(
0276         remove_reference_t<Stream>& next_layer)
0277       : next_layer_(next_layer)
0278     {
0279     }
0280 
0281     executor_type get_executor() const noexcept
0282     {
0283       return next_layer_.lowest_layer().get_executor();
0284     }
0285 
0286     template <typename WriteHandler, typename ConstBufferSequence>
0287     void operator()(WriteHandler&& handler,
0288         buffered_stream_storage* storage,
0289         const ConstBufferSequence& buffers) const
0290     {
0291       // If you get an error on the following line it means that your handler
0292       // does not meet the documented type requirements for a WriteHandler.
0293       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0294 
0295       using boost::asio::buffer_size;
0296       non_const_lvalue<WriteHandler> handler2(handler);
0297       if (buffer_size(buffers) == 0 || storage->size() < storage->capacity())
0298       {
0299         next_layer_.async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
0300             buffered_write_some_handler<ConstBufferSequence,
0301               decay_t<WriteHandler>>(
0302                 *storage, buffers, handler2.value));
0303       }
0304       else
0305       {
0306         initiate_async_buffered_flush<Stream>(this->next_layer_)(
0307             buffered_write_some_handler<ConstBufferSequence,
0308               decay_t<WriteHandler>>(
0309                 *storage, buffers, handler2.value),
0310             storage);
0311       }
0312     }
0313 
0314   private:
0315     remove_reference_t<Stream>& next_layer_;
0316   };
0317 } // namespace detail
0318 
0319 #if !defined(GENERATING_DOCUMENTATION)
0320 
0321 template <template <typename, typename> class Associator,
0322     typename ConstBufferSequence, typename WriteHandler,
0323     typename DefaultCandidate>
0324 struct associator<Associator,
0325     detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
0326     DefaultCandidate>
0327   : Associator<WriteHandler, DefaultCandidate>
0328 {
0329   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0330       const detail::buffered_write_some_handler<
0331         ConstBufferSequence, WriteHandler>& h) noexcept
0332   {
0333     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0334   }
0335 
0336   static auto get(
0337       const detail::buffered_write_some_handler<
0338         ConstBufferSequence, WriteHandler>& h,
0339       const DefaultCandidate& c) noexcept
0340     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0341   {
0342     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0343   }
0344 };
0345 
0346 #endif // !defined(GENERATING_DOCUMENTATION)
0347 
0348 template <typename Stream>
0349 template <typename ConstBufferSequence,
0350     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0351       std::size_t)) WriteHandler>
0352 inline auto buffered_write_stream<Stream>::async_write_some(
0353     const ConstBufferSequence& buffers, WriteHandler&& handler)
0354   -> decltype(
0355     async_initiate<WriteHandler,
0356       void (boost::system::error_code, std::size_t)>(
0357         declval<detail::initiate_async_buffered_write_some<Stream>>(),
0358         handler, declval<detail::buffered_stream_storage*>(), buffers))
0359 {
0360   return async_initiate<WriteHandler,
0361     void (boost::system::error_code, std::size_t)>(
0362       detail::initiate_async_buffered_write_some<Stream>(next_layer_),
0363       handler, &storage_, buffers);
0364 }
0365 
0366 template <typename Stream>
0367 template <typename ConstBufferSequence>
0368 std::size_t buffered_write_stream<Stream>::copy(
0369     const ConstBufferSequence& buffers)
0370 {
0371   using boost::asio::buffer_size;
0372   std::size_t orig_size = storage_.size();
0373   std::size_t space_avail = storage_.capacity() - orig_size;
0374   std::size_t bytes_avail = buffer_size(buffers);
0375   std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;
0376   storage_.resize(orig_size + length);
0377   return boost::asio::buffer_copy(
0378       storage_.data() + orig_size, buffers, length);
0379 }
0380 
0381 } // namespace asio
0382 } // namespace boost
0383 
0384 #include <boost/asio/detail/pop_options.hpp>
0385 
0386 #endif // BOOST_ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP