1[/ 2 / Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See accompanying 5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 /] 7 8[section:buffers Buffers] 9 10Fundamentally, I/O involves the transfer of data to and from contiguous regions 11of memory, called buffers. These buffers can be simply expressed as a tuple 12consisting of a pointer and a size in bytes. However, to allow the development 13of efficient network applications, Boost.Asio includes support for scatter-gather 14operations. These operations involve one or more buffers: 15 16* A scatter-read receives data into multiple buffers. 17* A gather-write transmits multiple buffers. 18 19Therefore we require an abstraction to represent a collection of buffers. The 20approach used in Boost.Asio is to define a type (actually two types) to 21represent a single buffer. These can be stored in a container, which may be 22passed to the scatter-gather operations. 23 24In addition to specifying buffers as a pointer and size in bytes, Boost.Asio makes a 25distinction between modifiable memory (called mutable) and non-modifiable 26memory (where the latter is created from the storage for a const-qualified 27variable). These two types could therefore be defined as follows: 28 29 typedef std::pair<void*, std::size_t> mutable_buffer; 30 typedef std::pair<const void*, std::size_t> const_buffer; 31 32Here, a mutable_buffer would be convertible to a const_buffer, but conversion 33in the opposite direction is not valid. 34 35However, Boost.Asio does not use the above definitions as-is, but instead defines two 36classes: `mutable_buffer` and `const_buffer`. The goal of these is to provide 37an opaque representation of contiguous memory, where: 38 39* Types behave as std::pair would in conversions. That is, a `mutable_buffer` is 40 convertible to a `const_buffer`, but the opposite conversion is disallowed. 41 42* There is protection against buffer overruns. Given a buffer instance, a user 43 can only create another buffer representing the same range of memory or a 44 sub-range of it. To provide further safety, the library also includes 45 mechanisms for automatically determining the size of a buffer from an array, 46 `boost::array` or `std::vector` of POD elements, or from a `std::string`. 47 48* The underlying memory is explicitly accessed using the `data()` member 49 function. In general an application should never need to do this, but it is 50 required by the library implementation to pass the raw memory to the 51 underlying operating system functions. 52 53Finally, multiple buffers can be passed to scatter-gather operations (such as 54[link boost_asio.reference.read read()] or [link boost_asio.reference.write write()]) by 55putting the buffer objects into a container. The `MutableBufferSequence` and 56`ConstBufferSequence` concepts have been defined so that containers such as 57`std::vector`, `std::list`, `std::array` or `boost::array` can be used. 58 59[heading Streambuf for Integration with Iostreams] 60 61The class `boost::asio::basic_streambuf` is derived from `std::basic_streambuf` to 62associate the input sequence and output sequence with one or more objects of 63some character array type, whose elements store arbitrary values. These 64character array objects are internal to the streambuf object, but direct access 65to the array elements is provided to permit them to be used with I/O 66operations, such as the send or receive operations of a socket: 67 68* The input sequence of the streambuf is accessible via the [link 69 boost_asio.reference.basic_streambuf.data data()] member function. The return type 70 of this function meets the `ConstBufferSequence` requirements. 71 72* The output sequence of the streambuf is accessible via the [link 73 boost_asio.reference.basic_streambuf.prepare prepare()] member function. The return 74 type of this function meets the `MutableBufferSequence` requirements. 75 76* Data is transferred from the front of the output sequence to the back of the 77 input sequence by calling the [link boost_asio.reference.basic_streambuf.commit 78 commit()] member function. 79 80* Data is removed from the front of the input sequence by calling the [link 81 boost_asio.reference.basic_streambuf.consume consume()] member function. 82 83The streambuf constructor accepts a `size_t` argument specifying the maximum of 84the sum of the sizes of the input sequence and output sequence. Any operation 85that would, if successful, grow the internal data beyond this limit will throw 86a `std::length_error` exception. 87 88[heading Bytewise Traversal of Buffer Sequences] 89 90The `buffers_iterator<>` class template allows buffer sequences (i.e. types 91meeting `MutableBufferSequence` or `ConstBufferSequence` requirements) to be 92traversed as though they were a contiguous sequence of bytes. Helper functions 93called buffers_begin() and buffers_end() are also provided, where the 94buffers_iterator<> template parameter is automatically deduced. 95 96As an example, to read a single line from a socket and into a `std::string`, 97you may write: 98 99 boost::asio::streambuf sb; 100 ... 101 std::size_t n = boost::asio::read_until(sock, sb, '\n'); 102 boost::asio::streambuf::const_buffers_type bufs = sb.data(); 103 std::string line( 104 boost::asio::buffers_begin(bufs), 105 boost::asio::buffers_begin(bufs) + n); 106 107[heading Buffer Debugging] 108 109Some standard library implementations, such as the one that ships with 110Microsoft Visual C++ 8.0 and later, provide a feature called iterator 111debugging. What this means is that the validity of iterators is checked at 112runtime. If a program tries to use an iterator that has been invalidated, an 113assertion will be triggered. For example: 114 115 std::vector<int> v(1) 116 std::vector<int>::iterator i = v.begin(); 117 v.clear(); // invalidates iterators 118 *i = 0; // assertion! 119 120Boost.Asio takes advantage of this feature to add buffer debugging. Consider the 121following code: 122 123 void dont_do_this() 124 { 125 std::string msg = "Hello, world!"; 126 boost::asio::async_write(sock, boost::asio::buffer(msg), my_handler); 127 } 128 129When you call an asynchronous read or write you need to ensure that the buffers 130for the operation are valid until the completion handler is called. In the 131above example, the buffer is the `std::string` variable `msg`. This variable is 132on the stack, and so it goes out of scope before the asynchronous operation 133completes. If you're lucky then the application will crash, but random failures 134are more likely. 135 136When buffer debugging is enabled, Boost.Asio stores an iterator into the string until 137the asynchronous operation completes, and then dereferences it to check its 138validity. In the above example you would observe an assertion failure just 139before Boost.Asio tries to call the completion handler. 140 141This feature is automatically made available for Microsoft Visual Studio 8.0 or 142later and for GCC when `_GLIBCXX_DEBUG` is defined. There is a performance cost 143to this checking, so buffer debugging is only enabled in debug builds. For 144other compilers it may be enabled by defining `BOOST_ASIO_ENABLE_BUFFER_DEBUGGING`. 145It can also be explicitly disabled by defining `BOOST_ASIO_DISABLE_BUFFER_DEBUGGING`. 146 147[heading See Also] 148 149[link boost_asio.reference.buffer buffer], 150[link boost_asio.reference.buffers_begin buffers_begin], 151[link boost_asio.reference.buffers_end buffers_end], 152[link boost_asio.reference.buffers_iterator buffers_iterator], 153[link boost_asio.reference.const_buffer const_buffer], 154[link boost_asio.reference.const_buffers_1 const_buffers_1], 155[link boost_asio.reference.mutable_buffer mutable_buffer], 156[link boost_asio.reference.mutable_buffers_1 mutable_buffers_1], 157[link boost_asio.reference.streambuf streambuf], 158[link boost_asio.reference.ConstBufferSequence ConstBufferSequence], 159[link boost_asio.reference.MutableBufferSequence MutableBufferSequence], 160[link boost_asio.examples.cpp03_examples.buffers buffers example (C++03)], 161[link boost_asio.examples.cpp11_examples.buffers buffers example (c++11)]. 162 163[endsect] 164