boost::capy::DynamicBuffer
Concept for resizable buffer types with prepare/commit semantics.
Synopsis
template<class T>
concept DynamicBuffer = requires(T& t, T const& ct, std::size_t n)
{
typename T::const_buffers_type;
typename T::mutable_buffers_type;
{ ct.size() } ‐> std::convertible_to<std::size_t>;
{ ct.max_size() } ‐> std::convertible_to<std::size_t>;
{ ct.capacity() } ‐> std::convertible_to<std::size_t>;
{ ct.data() } ‐> std::same_as<typename T::const_buffers_type>;
{ t.prepare(n) } ‐> std::same_as<typename T::mutable_buffers_type>;
t.commit(n);
t.consume(n);
} &&
ConstBufferSequence<typename T::const_buffers_type> &&
MutableBufferSequence<typename T::mutable_buffers_type>;
Description
Types satisfying this concept provide a two‐phase write model: call prepare(n) to get writable space, write data, then call commit(n) to make those bytes readable via data().
Semantic Requirements
‐ data() returns buffer sequence valid until next mutating operation ‐ prepare(n) returns buffer sequence valid until commit() or next prepare() ‐ Types may reference external storage; caller manages lifetime
Value Types vs Wrapper Adapters
Dynamic buffer types fall into two categories:
‐ Value types (e.g., flat_dynamic_buffer) store bookkeeping internally. Passing as rvalue to a coroutine loses state on suspend.
‐ Wrapper adapters (e.g., string_buffers) reference external storage and are safe as rvalues since the external object persists.
Conforming Signatures
For non‐coroutine functions, use DynamicBuffer auto&:
void fill( DynamicBuffer auto& buffers );
For coroutine functions, use DynamicBufferParam auto&& instead. This concept enforces lifetime safety: it accepts lvalues of any DynamicBuffer, but restricts rvalues to adapter types only. Using plain DynamicBuffer in coroutines allows dangerous rvalue passing that compiles but silently loses data on suspend.
io_task<std::size_t>
read( ReadSource auto& src, DynamicBufferParam auto&& buffers );
Example
flat_dynamic_buffer fb( storage, sizeof( storage ) );
auto mb = fb.prepare( 100 ); // get writable region
std::size_t n = read( sock, mb );
fb.commit( n ); // make n bytes readable
process( fb.data() ); // access committed data
fb.consume( fb.size() ); // discard processed data
See Also
DynamicBufferParam
Created with MrDocs