boost::capy::WriteSink
Concept for types providing complete writes with EOF signaling.
Synopsis
template<typename T>
concept WriteSink = WriteStream<T> &&
requires(T& sink, const_buffer_archetype buffers)
{
{ sink.write(buffers) } ‐> IoAwaitable;
requires awaitable_decomposes_to<
decltype(sink.write(buffers)),
std::error_code, std::size_t>;
{ sink.write_eof(buffers) } ‐> IoAwaitable;
requires awaitable_decomposes_to<
decltype(sink.write_eof(buffers)),
std::error_code, std::size_t>;
{ sink.write_eof() } ‐> IoAwaitable;
requires awaitable_decomposes_to<
decltype(sink.write_eof()),
std::error_code>;
};
Description
A type satisfies WriteSink if it satisfies WriteStream and additionally provides write, write_eof(buffers), and write_eof() member functions that are IoAwaitable.
WriteSink refines WriteStream. Every WriteSink is a WriteStream. Algorithms constrained on WriteStream accept both raw streams and sinks.
Syntactic Requirements
-
`T` must satisfy
WriteStream(provides `write_some`) -
`T` must provide a `write` member function template accepting any
ConstBufferSequence, returning an awaitable that decomposes to `(error_code,std::size_t)` -
`T` must provide a `write_eof` member function template accepting any
ConstBufferSequence, returning an awaitable that decomposes to `(error_code,std::size_t)` -
`T` must provide a `write_eof` member function taking no arguments, returning an awaitable that decomposes to `(error_code)`
-
All return types must satisfy
IoAwaitable
Semantic Requirements
The inherited write_some operation writes one or more bytes (partial write). See WriteStream.
The write operation consumes the entire buffer sequence:
-
On success: `!ec`, and `n` equals `buffer_size( buffers )`.
-
On error: `ec`, and `n` indicates the number of bytes written before the error.
The write_eof(buffers) operation writes the entire buffer sequence and signals end‐of‐stream atomically:
-
On success: `!ec`, `n` equals `buffer_size( buffers )`, and the sink is finalized.
-
On error: `ec`, and `n` indicates the number of bytes written before the error.
The write_eof() operation signals end‐of‐stream with no data:
-
On success: `!ec`, and the sink is finalized.
-
On error: `ec`.
After write_eof (either overload) returns successfully, no further writes or EOF signals are permitted.
Buffer Lifetime
The caller must ensure that the memory referenced by the buffer sequence remains valid until the co_await expression returns.
Conforming Signatures
template< ConstBufferSequence Buffers >
IoAwaitable auto write_some( Buffers buffers ); // inherited
template< ConstBufferSequence Buffers >
IoAwaitable auto write( Buffers buffers );
template< ConstBufferSequence Buffers >
IoAwaitable auto write_eof( Buffers buffers );
IoAwaitable auto write_eof();
|
Coroutine Buffer Lifetime: When implementing coroutine member functions, prefer accepting buffer sequences by value rather than by reference. Buffer sequences passed by reference may become dangling if the caller's stack frame is destroyed before the coroutine completes. Passing by value ensures the buffer sequence is copied into the coroutine frame and remains valid across suspension points. |
Example
template< WriteSink Sink >
task<> send_body( Sink& sink, std::string_view data )
{
// Atomic: write all data and signal EOF
auto [ec, n] = co_await sink.write_eof(
make_buffer( data ) );
}
// Or separately:
template< WriteSink Sink >
task<> send_body2( Sink& sink, std::string_view data )
{
auto [ec, n] = co_await sink.write(
make_buffer( data ) );
if( ec )
co_return;
auto [ec2] = co_await sink.write_eof();
}
See Also
WriteStream, IoAwaitable, ConstBufferSequence, awaitable_decomposes_to
Created with MrDocs