123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- [/
- / Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
- /
- / Distributed under the Boost Software License, Version 1.0. (See accompanying
- / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- /]
- [section:buffers Buffers]
- Fundamentally, I/O involves the transfer of data to and from contiguous regions
- of memory, called buffers. These buffers can be simply expressed as a tuple
- consisting of a pointer and a size in bytes. However, to allow the development
- of efficient network applications, Boost.Asio includes support for scatter-gather
- operations. These operations involve one or more buffers:
- * A scatter-read receives data into multiple buffers.
- * A gather-write transmits multiple buffers.
- Therefore we require an abstraction to represent a collection of buffers. The
- approach used in Boost.Asio is to define a type (actually two types) to
- represent a single buffer. These can be stored in a container, which may be
- passed to the scatter-gather operations.
- In addition to specifying buffers as a pointer and size in bytes, Boost.Asio makes a
- distinction between modifiable memory (called mutable) and non-modifiable
- memory (where the latter is created from the storage for a const-qualified
- variable). These two types could therefore be defined as follows:
- typedef std::pair<void*, std::size_t> mutable_buffer;
- typedef std::pair<const void*, std::size_t> const_buffer;
- Here, a mutable_buffer would be convertible to a const_buffer, but conversion
- in the opposite direction is not valid.
- However, Boost.Asio does not use the above definitions as-is, but instead defines two
- classes: `mutable_buffer` and `const_buffer`. The goal of these is to provide
- an opaque representation of contiguous memory, where:
- * Types behave as std::pair would in conversions. That is, a `mutable_buffer` is
- convertible to a `const_buffer`, but the opposite conversion is disallowed.
- * There is protection against buffer overruns. Given a buffer instance, a user
- can only create another buffer representing the same range of memory or a
- sub-range of it. To provide further safety, the library also includes
- mechanisms for automatically determining the size of a buffer from an array,
- `boost::array` or `std::vector` of POD elements, or from a `std::string`.
- * The underlying memory is explicitly accessed using the `data()` member
- function. In general an application should never need to do this, but it is
- required by the library implementation to pass the raw memory to the
- underlying operating system functions.
- Finally, multiple buffers can be passed to scatter-gather operations (such as
- [link boost_asio.reference.read read()] or [link boost_asio.reference.write write()]) by
- putting the buffer objects into a container. The `MutableBufferSequence` and
- `ConstBufferSequence` concepts have been defined so that containers such as
- `std::vector`, `std::list`, `std::array` or `boost::array` can be used.
- [heading Streambuf for Integration with Iostreams]
- The class `boost::asio::basic_streambuf` is derived from `std::basic_streambuf` to
- associate the input sequence and output sequence with one or more objects of
- some character array type, whose elements store arbitrary values. These
- character array objects are internal to the streambuf object, but direct access
- to the array elements is provided to permit them to be used with I/O
- operations, such as the send or receive operations of a socket:
- * The input sequence of the streambuf is accessible via the [link
- boost_asio.reference.basic_streambuf.data data()] member function. The return type
- of this function meets the `ConstBufferSequence` requirements.
- * The output sequence of the streambuf is accessible via the [link
- boost_asio.reference.basic_streambuf.prepare prepare()] member function. The return
- type of this function meets the `MutableBufferSequence` requirements.
- * Data is transferred from the front of the output sequence to the back of the
- input sequence by calling the [link boost_asio.reference.basic_streambuf.commit
- commit()] member function.
- * Data is removed from the front of the input sequence by calling the [link
- boost_asio.reference.basic_streambuf.consume consume()] member function.
- The streambuf constructor accepts a `size_t` argument specifying the maximum of
- the sum of the sizes of the input sequence and output sequence. Any operation
- that would, if successful, grow the internal data beyond this limit will throw
- a `std::length_error` exception.
- [heading Bytewise Traversal of Buffer Sequences]
- The `buffers_iterator<>` class template allows buffer sequences (i.e. types
- meeting `MutableBufferSequence` or `ConstBufferSequence` requirements) to be
- traversed as though they were a contiguous sequence of bytes. Helper functions
- called buffers_begin() and buffers_end() are also provided, where the
- buffers_iterator<> template parameter is automatically deduced.
- As an example, to read a single line from a socket and into a `std::string`,
- you may write:
- boost::asio::streambuf sb;
- ...
- std::size_t n = boost::asio::read_until(sock, sb, '\n');
- boost::asio::streambuf::const_buffers_type bufs = sb.data();
- std::string line(
- boost::asio::buffers_begin(bufs),
- boost::asio::buffers_begin(bufs) + n);
- [heading Buffer Debugging]
- Some standard library implementations, such as the one that ships with
- Microsoft Visual C++ 8.0 and later, provide a feature called iterator
- debugging. What this means is that the validity of iterators is checked at
- runtime. If a program tries to use an iterator that has been invalidated, an
- assertion will be triggered. For example:
- std::vector<int> v(1)
- std::vector<int>::iterator i = v.begin();
- v.clear(); // invalidates iterators
- *i = 0; // assertion!
- Boost.Asio takes advantage of this feature to add buffer debugging. Consider the
- following code:
- void dont_do_this()
- {
- std::string msg = "Hello, world!";
- boost::asio::async_write(sock, boost::asio::buffer(msg), my_handler);
- }
- When you call an asynchronous read or write you need to ensure that the buffers
- for the operation are valid until the completion handler is called. In the
- above example, the buffer is the `std::string` variable `msg`. This variable is
- on the stack, and so it goes out of scope before the asynchronous operation
- completes. If you're lucky then the application will crash, but random failures
- are more likely.
- When buffer debugging is enabled, Boost.Asio stores an iterator into the string until
- the asynchronous operation completes, and then dereferences it to check its
- validity. In the above example you would observe an assertion failure just
- before Boost.Asio tries to call the completion handler.
- This feature is automatically made available for Microsoft Visual Studio 8.0 or
- later and for GCC when `_GLIBCXX_DEBUG` is defined. There is a performance cost
- to this checking, so buffer debugging is only enabled in debug builds. For
- other compilers it may be enabled by defining `BOOST_ASIO_ENABLE_BUFFER_DEBUGGING`.
- It can also be explicitly disabled by defining `BOOST_ASIO_DISABLE_BUFFER_DEBUGGING`.
- [heading See Also]
- [link boost_asio.reference.buffer buffer],
- [link boost_asio.reference.buffers_begin buffers_begin],
- [link boost_asio.reference.buffers_end buffers_end],
- [link boost_asio.reference.buffers_iterator buffers_iterator],
- [link boost_asio.reference.const_buffer const_buffer],
- [link boost_asio.reference.const_buffers_1 const_buffers_1],
- [link boost_asio.reference.mutable_buffer mutable_buffer],
- [link boost_asio.reference.mutable_buffers_1 mutable_buffers_1],
- [link boost_asio.reference.streambuf streambuf],
- [link boost_asio.reference.ConstBufferSequence ConstBufferSequence],
- [link boost_asio.reference.MutableBufferSequence MutableBufferSequence],
- [link boost_asio.examples.cpp03_examples.buffers buffers example (C++03)],
- [link boost_asio.examples.cpp11_examples.buffers buffers example (c++11)].
- [endsect]
|