16 Buffers [buffer]

16.2 Requirements [buffer.reqmts]

16.2.1 Mutable buffer sequence requirements [buffer.reqmts.mutablebuffersequence]

A mutable buffer sequence represents a set of memory regions that may be used to receive the output of an operation, such as the receive operation of a socket.

A type X meets the MutableBufferSequence requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed in Table [tab:buffer.reqmts.mutablebuffersequence.requirements].

In Table [tab:buffer.reqmts.mutablebuffersequence.requirements], x denotes a (possibly const) value of type X, and u denotes an identifier.

Table 12 — MutableBufferSequence requirements
expressionreturn typeassertion/note
pre/post-condition
net::buffer_sequence_begin(x)
net::buffer_sequence_end(x)
An iterator type whose reference type is convertible to mutable_buffer, and which satisfies all the requirements for bidirectional iterators (C++ 2014 [bidirectional.iterators]) except that:
  • there is no requirement that operator-> is provided, and

  • there is no requirement that reference be a reference type.

For a dereferenceable iterator, no increment, decrement, or dereference operation, or conversion of the reference type to mutable_buffer, shall exit via an exception.
X u(x); post:
equal(
  net::buffer_sequence_begin(x),
  net::buffer_sequence_end(x),
  net::buffer_sequence_begin(u),
  net::buffer_sequence_end(u),
  [](const mutable_buffer& b1,
     const mutable_buffer& b2)
   {
     return b1.data() == b2.data()
         && b1.size() == b2.size();
   })

16.2.2 Constant buffer sequence requirements [buffer.reqmts.constbuffersequence]

A constant buffer sequence represents a set of memory regions that may be used as input to an operation, such as the send operation of a socket.

A type X meets the ConstBufferSequence requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed in Table [tab:buffer.reqmts.constbuffersequence.requirements].

In Table [tab:buffer.reqmts.constbuffersequence.requirements], x denotes a (possibly const) value of type X, and u denotes an identifier.

Table 13 — ConstBufferSequence requirements
expressionreturn typeassertion/note
pre/post-condition
net::buffer_sequence_begin(x)
net::buffer_sequence_end(x)
An iterator type whose reference type is convertible to const_buffer, and which satisfies all the requirements for bidirectional iterators (C++ 2014 [bidirectional.iterators]) except that:
  • there is no requirement that operator-> is provided, and

  • there is no requirement that reference be a reference type.

For a dereferenceable iterator, no increment, decrement, or dereference operation, or conversion of the reference type to const_buffer, shall exit via an exception.
X u(x); post:
equal(
  net::buffer_sequence_begin(x),
  net::buffer_sequence_end(x),
  net::buffer_sequence_begin(u),
  net::buffer_sequence_end(u),
  [](const const_buffer& b1,
     const const_buffer& b2)
   {
     return b1.data() == b2.data()
         && b1.size() == b2.size();
   })

16.2.3 Buffer size [buffer.reqmts.size]

Several places in this document make unqualified calls to buffer_size. The context in which these calls are evaluated shall ensure that a unary non-member function named buffer_size is selected via overload resolution (C++ 2014 [over.match]) on a candidate set that includes:

  • the buffer_size function template defined in <experimental/buffer> ([buffer.synop]) and

  • the lookup set produced by argument-dependent lookup (C++ 2014 [basic.lookup.argdep]).

16.2.4 Dynamic buffer requirements [buffer.reqmts.dynamicbuffer]

A dynamic buffer encapsulates memory storage that may be automatically resized as required, where the memory is divided into two regions: readable bytes followed by writable bytes. These memory regions are internal to the dynamic buffer, but direct access to the elements is provided to permit them to be efficiently used with I/O operations. [ Note: Such as the send or receive operations of a socket. The readable bytes would be used as the constant buffer sequence for send, and the writable bytes used as the mutable buffer sequence for receive.  — end note ] Data written to the writable bytes of a dynamic buffer object is appended to the readable bytes of the same object.

A type X meets the DynamicBuffer requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and MoveConstructible (C++ 2014 [moveconstructible]), as well as the additional requirements listed in Table [tab:buffer.reqmts.dynamicbuffer.requirements].

In Table [tab:buffer.reqmts.dynamicbuffer.requirements], x denotes a value of type X, x1 denotes a (possibly const) value of type X, and n denotes a (possibly const) value of type size_t.

Table 14 — DynamicBuffer requirements
expressiontypeassertion/note pre/post-conditions
X::const_buffers_type type meeting ConstBufferSequence ([buffer.reqmts.constbuffersequence]) requirements. This type represents the memory associated with the readable bytes.
X::mutable_buffers_type type meeting MutableBufferSequence ([buffer.reqmts.constbuffersequence]) requirements. This type represents the memory associated with the writable bytes.
x1.size() size_t Returns the number of readable bytes.
x1.max_size() size_t Returns the maximum number of bytes, both readable and writable, that can be held by x1.
x1.capacity() size_t Returns the maximum number of bytes, both readable and writable, that can be held by x1 without requiring reallocation.
x1.data() X::const_buffers_type Returns a constant buffer sequence u that represents the readable bytes, and where buffer_size(u) == size().
x.prepare(n) X::mutable_buffers_type Returns a mutable buffer sequence u representing the writable bytes, and where buffer_size(u) == n. The dynamic buffer reallocates memory as required. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated.
Throws: length_error if size() + n exceeds max_size().
x.commit(n) Appends n bytes from the start of the writable bytes to the end of the readable bytes. The remainder of the writable bytes are discarded. If n is greater than the number of writable bytes, all writable bytes are appended to the readable bytes. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated.
x.consume(n) Removes n bytes from beginning of the readable bytes. If n is greater than the number of readable bytes, all readable bytes are removed. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated.

16.2.5 Requirements on read and write operations [buffer.reqmts.read.write]

A read operation is an operation that reads data into a mutable buffer sequence argument of a type meeting MutableBufferSequence ([buffer.reqmts.mutablebuffersequence]) requirements. The mutable buffer sequence specifies memory where the data should be placed. A read operation shall always fill a buffer in the sequence completely before proceeding to the next.

A write operation is an operation that writes data from a constant buffer sequence argument of a type meeting ConstBufferSequence ([buffer.reqmts.constbuffersequence]) requirements. The constant buffer sequence specifies memory where the data to be written is located. A write operation shall always write a buffer in the sequence completely before proceeding to the next.

If a read or write operation is also an asynchronous operation ([async.reqmts.async]), the operation shall maintain one or more copies of the buffer sequence until such time as the operation no longer requires access to the memory specified by the buffers in the sequence. The program shall ensure the memory remains valid until:

  • the last copy of the buffer sequence is destroyed, or

  • the completion handler for the asynchronous operation is invoked,

whichever comes first.