buffered_write_stream.hpp
Go to the documentation of this file.
00001 //
00002 // buffered_write_stream.hpp
00003 // ~~~~~~~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_BUFFERED_WRITE_STREAM_HPP
00012 #define ASIO_BUFFERED_WRITE_STREAM_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/push_options.hpp"
00021 #include <cstddef>
00022 #include <cstring>
00023 #include <boost/config.hpp>
00024 #include <boost/type_traits.hpp>
00025 #include "asio/detail/pop_options.hpp"
00026 
00027 #include "asio/buffered_write_stream_fwd.hpp"
00028 #include "asio/buffer.hpp"
00029 #include "asio/completion_condition.hpp"
00030 #include "asio/error.hpp"
00031 #include "asio/io_service.hpp"
00032 #include "asio/write.hpp"
00033 #include "asio/detail/bind_handler.hpp"
00034 #include "asio/detail/buffered_stream_storage.hpp"
00035 #include "asio/detail/noncopyable.hpp"
00036 
00037 namespace asio {
00038 
00040 
00051 template <typename Stream>
00052 class buffered_write_stream
00053   : private noncopyable
00054 {
00055 public:
00057   typedef typename boost::remove_reference<Stream>::type next_layer_type;
00058 
00060   typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
00061 
00062 #if defined(GENERATING_DOCUMENTATION)
00063 
00064   static const std::size_t default_buffer_size = implementation_defined;
00065 #else
00066   BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
00067 #endif
00068 
00070   template <typename Arg>
00071   explicit buffered_write_stream(Arg& a)
00072     : next_layer_(a),
00073       storage_(default_buffer_size)
00074   {
00075   }
00076 
00078   template <typename Arg>
00079   buffered_write_stream(Arg& a, std::size_t buffer_size)
00080     : next_layer_(a),
00081       storage_(buffer_size)
00082   {
00083   }
00084 
00086   next_layer_type& next_layer()
00087   {
00088     return next_layer_;
00089   }
00090 
00092   lowest_layer_type& lowest_layer()
00093   {
00094     return next_layer_.lowest_layer();
00095   }
00096 
00099   asio::io_service& io_service()
00100   {
00101     return next_layer_.get_io_service();
00102   }
00103 
00105   asio::io_service& get_io_service()
00106   {
00107     return next_layer_.get_io_service();
00108   }
00109 
00111   void close()
00112   {
00113     next_layer_.close();
00114   }
00115 
00117   asio::error_code close(asio::error_code& ec)
00118   {
00119     return next_layer_.close(ec);
00120   }
00121 
00125   std::size_t flush()
00126   {
00127     std::size_t bytes_written = write(next_layer_,
00128         buffer(storage_.data(), storage_.size()));
00129     storage_.consume(bytes_written);
00130     return bytes_written;
00131   }
00132 
00136   std::size_t flush(asio::error_code& ec)
00137   {
00138     std::size_t bytes_written = write(next_layer_,
00139         buffer(storage_.data(), storage_.size()),
00140         transfer_all(), ec);
00141     storage_.consume(bytes_written);
00142     return bytes_written;
00143   }
00144 
00145   template <typename WriteHandler>
00146   class flush_handler
00147   {
00148   public:
00149     flush_handler(asio::io_service& io_service,
00150         detail::buffered_stream_storage& storage, WriteHandler handler)
00151       : io_service_(io_service),
00152         storage_(storage),
00153         handler_(handler)
00154     {
00155     }
00156 
00157     void operator()(const asio::error_code& ec,
00158         std::size_t bytes_written)
00159     {
00160       storage_.consume(bytes_written);
00161       io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written));
00162     }
00163 
00164   private:
00165     asio::io_service& io_service_;
00166     detail::buffered_stream_storage& storage_;
00167     WriteHandler handler_;
00168   };
00169 
00171   template <typename WriteHandler>
00172   void async_flush(WriteHandler handler)
00173   {
00174     async_write(next_layer_, buffer(storage_.data(), storage_.size()),
00175         flush_handler<WriteHandler>(get_io_service(), storage_, handler));
00176   }
00177 
00180   template <typename ConstBufferSequence>
00181   std::size_t write_some(const ConstBufferSequence& buffers)
00182   {
00183     if (storage_.size() == storage_.capacity())
00184       flush();
00185     return copy(buffers);
00186   }
00187 
00190   template <typename ConstBufferSequence>
00191   std::size_t write_some(const ConstBufferSequence& buffers,
00192       asio::error_code& ec)
00193   {
00194     ec = asio::error_code();
00195     if (storage_.size() == storage_.capacity() && !flush(ec))
00196       return 0;
00197     return copy(buffers);
00198   }
00199 
00200   template <typename ConstBufferSequence, typename WriteHandler>
00201   class write_some_handler
00202   {
00203   public:
00204     write_some_handler(asio::io_service& io_service,
00205         detail::buffered_stream_storage& storage,
00206         const ConstBufferSequence& buffers, WriteHandler handler)
00207       : io_service_(io_service),
00208         storage_(storage),
00209         buffers_(buffers),
00210         handler_(handler)
00211     {
00212     }
00213 
00214     void operator()(const asio::error_code& ec, std::size_t)
00215     {
00216       if (ec)
00217       {
00218         std::size_t length = 0;
00219         io_service_.dispatch(detail::bind_handler(handler_, ec, length));
00220       }
00221       else
00222       {
00223         using namespace std; // For memcpy.
00224 
00225         std::size_t orig_size = storage_.size();
00226         std::size_t space_avail = storage_.capacity() - orig_size;
00227         std::size_t bytes_copied = 0;
00228 
00229         typename ConstBufferSequence::const_iterator iter = buffers_.begin();
00230         typename ConstBufferSequence::const_iterator end = buffers_.end();
00231         for (; iter != end && space_avail > 0; ++iter)
00232         {
00233           std::size_t bytes_avail = buffer_size(*iter);
00234           std::size_t length = (bytes_avail < space_avail)
00235             ? bytes_avail : space_avail;
00236           storage_.resize(orig_size + bytes_copied + length);
00237           memcpy(storage_.data() + orig_size + bytes_copied,
00238               buffer_cast<const void*>(*iter), length);
00239           bytes_copied += length;
00240           space_avail -= length;
00241         }
00242 
00243         io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
00244       }
00245     }
00246 
00247   private:
00248     asio::io_service& io_service_;
00249     detail::buffered_stream_storage& storage_;
00250     ConstBufferSequence buffers_;
00251     WriteHandler handler_;
00252   };
00253 
00256   template <typename ConstBufferSequence, typename WriteHandler>
00257   void async_write_some(const ConstBufferSequence& buffers,
00258       WriteHandler handler)
00259   {
00260     if (storage_.size() == storage_.capacity())
00261     {
00262       async_flush(write_some_handler<ConstBufferSequence, WriteHandler>(
00263             get_io_service(), storage_, buffers, handler));
00264     }
00265     else
00266     {
00267       std::size_t bytes_copied = copy(buffers);
00268       get_io_service().post(detail::bind_handler(
00269             handler, asio::error_code(), bytes_copied));
00270     }
00271   }
00272 
00275   template <typename MutableBufferSequence>
00276   std::size_t read_some(const MutableBufferSequence& buffers)
00277   {
00278     return next_layer_.read_some(buffers);
00279   }
00280 
00283   template <typename MutableBufferSequence>
00284   std::size_t read_some(const MutableBufferSequence& buffers,
00285       asio::error_code& ec)
00286   {
00287     return next_layer_.read_some(buffers, ec);
00288   }
00289 
00292   template <typename MutableBufferSequence, typename ReadHandler>
00293   void async_read_some(const MutableBufferSequence& buffers,
00294       ReadHandler handler)
00295   {
00296     next_layer_.async_read_some(buffers, handler);
00297   }
00298 
00301   template <typename MutableBufferSequence>
00302   std::size_t peek(const MutableBufferSequence& buffers)
00303   {
00304     return next_layer_.peek(buffers);
00305   }
00306 
00309   template <typename MutableBufferSequence>
00310   std::size_t peek(const MutableBufferSequence& buffers,
00311       asio::error_code& ec)
00312   {
00313     return next_layer_.peek(buffers, ec);
00314   }
00315 
00317   std::size_t in_avail()
00318   {
00319     return next_layer_.in_avail();
00320   }
00321 
00323   std::size_t in_avail(asio::error_code& ec)
00324   {
00325     return next_layer_.in_avail(ec);
00326   }
00327 
00328 private:
00331   template <typename ConstBufferSequence>
00332   std::size_t copy(const ConstBufferSequence& buffers)
00333   {
00334     using namespace std; // For memcpy.
00335 
00336     std::size_t orig_size = storage_.size();
00337     std::size_t space_avail = storage_.capacity() - orig_size;
00338     std::size_t bytes_copied = 0;
00339 
00340     typename ConstBufferSequence::const_iterator iter = buffers.begin();
00341     typename ConstBufferSequence::const_iterator end = buffers.end();
00342     for (; iter != end && space_avail > 0; ++iter)
00343     {
00344       std::size_t bytes_avail = buffer_size(*iter);
00345       std::size_t length = (bytes_avail < space_avail)
00346         ? bytes_avail : space_avail;
00347       storage_.resize(orig_size + bytes_copied + length);
00348       memcpy(storage_.data() + orig_size + bytes_copied,
00349           buffer_cast<const void*>(*iter), length);
00350       bytes_copied += length;
00351       space_avail -= length;
00352     }
00353 
00354     return bytes_copied;
00355   }
00356 
00358   Stream next_layer_;
00359 
00360   // The data in the buffer.
00361   detail::buffered_stream_storage storage_;
00362 };
00363 
00364 } // namespace asio
00365 
00366 #include "asio/detail/pop_options.hpp"
00367 
00368 #endif // ASIO_BUFFERED_WRITE_STREAM_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39