Skip to content

Commit c2327cf

Browse files
committed
Docs: fix wrong namespaces, signatures, and behavior in composed-ops guide
Fixes #211: - corosio::read/write → capy::read/write (correct namespace) - Include paths: boost/corosio/ → boost/capy/ - read-into-string uses string_dynamic_buffer, not bare std::string - Return type is io_task<std::size_t>, not task<io_result<std::size_t>> - capy::error::eof → capy::cond::eof (error condition, not error code) - Remove incorrect write() zero-byte → broken_pipe claim - boost::system::system_error → capy::detail::throw_system_error - Template constraints use terse syntax matching actual signatures
1 parent 3fc8c97 commit c2327cf

1 file changed

Lines changed: 60 additions & 62 deletions

File tree

doc/modules/ROOT/pages/4.guide/4g.composed-operations.adoc

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ and `write_some()` functions to provide higher-level guarantees.
1717
Code snippets assume:
1818
[source,cpp]
1919
----
20-
#include <boost/corosio/read.hpp>
21-
#include <boost/corosio/write.hpp>
20+
#include <boost/capy/read.hpp>
21+
#include <boost/capy/write.hpp>
22+
#include <boost/capy/buffers/string_dynamic_buffer.hpp>
2223
#include <boost/capy/buffers.hpp>
2324
2425
namespace corosio = boost::corosio;
@@ -42,88 +43,82 @@ auto [ec, n] = co_await s.read_some(
4243
For many use cases, you need to transfer a specific amount of data. Composed
4344
operations provide these guarantees.
4445

45-
== corosio::read()
46+
== capy::read()
4647

4748
The `read()` function reads until the buffer is full or an error occurs:
4849

4950
[source,cpp]
5051
----
5152
char buf[1024];
52-
auto [ec, n] = co_await corosio::read(
53+
auto [ec, n] = co_await capy::read(
5354
stream, capy::mutable_buffer(buf, sizeof(buf)));
5455
5556
// Either:
5657
// - n == 1024 and ec is default (success)
57-
// - ec is error::eof and n < 1024 (reached end of stream)
58+
// - ec == capy::cond::eof and n < 1024 (reached end of stream)
5859
// - ec is some other error
5960
----
6061

6162
=== Signature
6263

6364
[source,cpp]
6465
----
65-
template<capy::mutable_buffer_sequence MutableBufferSequence>
66-
capy::task<io_result<std::size_t>>
67-
read(io_stream& ios, MutableBufferSequence const& buffers);
66+
auto
67+
read(
68+
ReadStream auto& stream,
69+
MutableBufferSequence auto const& buffers) ->
70+
capy::io_task<std::size_t>;
6871
----
6972

7073
=== Behavior
7174

7275
1. Calls `read_some()` repeatedly until all buffers are filled
73-
2. If `read_some()` returns 0 bytes, returns `capy::error::eof`
74-
3. If an error occurs, returns immediately with bytes read so far
75-
4. On success, returns total bytes (equals `buffer_size(buffers)`)
76+
2. If `read_some()` returns an error (including `cond::eof`), returns
77+
immediately with bytes read so far
78+
3. On success, returns total bytes (equals `buffer_size(buffers)`)
7679

77-
== corosio::read() into std::string
80+
== capy::read() into a dynamic buffer
7881

79-
A special overload reads until EOF, growing the string as needed:
82+
A second overload reads until EOF, growing the buffer as needed. Use
83+
`capy::string_dynamic_buffer` to wrap a `std::string`:
8084

8185
[source,cpp]
8286
----
8387
std::string content;
84-
auto [ec, n] = co_await corosio::read(stream, content);
88+
auto [ec, n] = co_await capy::read(
89+
stream, capy::string_dynamic_buffer(&content));
8590
86-
// Either:
87-
// - ec == capy::error::eof (normal termination)
88-
// - ec is some error
89-
// content contains all data read
91+
// On success (EOF reached): ec is default, n is total bytes read
92+
// On error: ec is the error, n is bytes read before the error
9093
----
9194

9295
=== Signature
9396

9497
[source,cpp]
9598
----
96-
capy::task<io_result<std::size_t>>
97-
read(io_stream& ios, std::string& s);
99+
auto
100+
read(
101+
ReadStream auto& stream,
102+
DynamicBufferParam auto&& buffers,
103+
std::size_t initial_amount = 2048) ->
104+
capy::io_task<std::size_t>;
98105
----
99106

100107
=== Behavior
101108

102-
1. Preserves existing string content
103-
2. Grows string as needed (starts with 2048 bytes, grows 1.5x)
104-
3. Reads until EOF or error
105-
4. Resizes string to actual data size before returning
106-
5. Returns `n` = new bytes read (not including original content)
107-
108-
=== Growth Strategy
109-
110-
The function uses an efficient growth strategy:
111-
112-
* Initial capacity: existing size + 2048
113-
* Growth factor: 1.5x when buffer fills
114-
* Maximum: `string::max_size()`
115-
116-
If the string reaches `max_size()` with more data available, returns
117-
`errc::value_too_large`.
109+
1. Prepares `initial_amount` bytes via `buffers.prepare()`, then reads
110+
2. Grows 1.5x when the prepared buffer fills completely
111+
3. On `cond::eof`: returns success with total bytes read
112+
4. On any other error: returns immediately with bytes read so far
118113

119-
== corosio::write()
114+
== capy::write()
120115

121116
The `write()` function writes all data or fails:
122117

123118
[source,cpp]
124119
----
125120
std::string msg = "Hello, World!";
126-
auto [ec, n] = co_await corosio::write(
121+
auto [ec, n] = co_await capy::write(
127122
stream, capy::const_buffer(msg.data(), msg.size()));
128123
129124
// Either:
@@ -135,17 +130,18 @@ auto [ec, n] = co_await corosio::write(
135130

136131
[source,cpp]
137132
----
138-
template<capy::const_buffer_sequence ConstBufferSequence>
139-
capy::task<io_result<std::size_t>>
140-
write(io_stream& ios, ConstBufferSequence const& buffers);
133+
auto
134+
write(
135+
WriteStream auto& stream,
136+
ConstBufferSequence auto const& buffers) ->
137+
capy::io_task<std::size_t>;
141138
----
142139

143140
=== Behavior
144141

145142
1. Calls `write_some()` repeatedly until all buffers are written
146-
2. If `write_some()` returns 0 bytes, returns `errc::broken_pipe`
147-
3. If an error occurs, returns immediately with bytes written so far
148-
4. On success, returns total bytes (equals `buffer_size(buffers)`)
143+
2. If an error occurs, returns immediately with bytes written so far
144+
3. On success, returns total bytes (equals `buffer_size(buffers)`)
149145

150146
== consuming_buffers Helper
151147

@@ -193,10 +189,10 @@ The iterator returns adjusted buffers accounting for consumed bytes.
193189

194190
[source,cpp]
195191
----
196-
auto [ec, n] = co_await corosio::read(stream, buf);
192+
auto [ec, n] = co_await capy::read(stream, buf);
197193
if (ec)
198194
{
199-
if (ec == capy::error::eof)
195+
if (ec == capy::cond::eof)
200196
std::cout << "End of stream, read " << n << " bytes\n";
201197
else
202198
std::cerr << "Error: " << ec.message() << "\n";
@@ -208,23 +204,25 @@ if (ec)
208204
[source,cpp]
209205
----
210206
// For write (EOF doesn't apply)
211-
auto n = (co_await corosio::write(stream, buf)).value();
207+
auto [wec, n] = co_await capy::write(stream, buf);
208+
if (wec)
209+
capy::detail::throw_system_error(wec);
212210
213211
// For read (need to handle EOF)
214-
auto [ec, n] = co_await corosio::read(stream, buf);
215-
if (ec && ec != capy::error::eof)
216-
throw boost::system::system_error(ec);
212+
auto [rec, rn] = co_await capy::read(stream, buf);
213+
if (rec && rec != capy::cond::eof)
214+
capy::detail::throw_system_error(rec);
217215
----
218216

219217
== Cancellation
220218

221219
Composed operations support cancellation through the affine protocol. When
222-
cancelled, they return with `operation_canceled` and the partial byte count.
220+
cancelled, they return with `cond::canceled` and the partial byte count.
223221

224222
[source,cpp]
225223
----
226-
auto [ec, n] = co_await corosio::read(stream, large_buffer);
227-
if (ec == make_error_code(system::errc::operation_canceled))
224+
auto [ec, n] = co_await capy::read(stream, large_buffer);
225+
if (ec == capy::cond::canceled)
228226
std::cout << "Cancelled after reading " << n << " bytes\n";
229227
----
230228

@@ -238,11 +236,11 @@ For optimal performance with multiple buffers:
238236
----
239237
// Efficient: single system call per read_some()
240238
std::array<capy::mutable_buffer, 2> bufs = {...};
241-
co_await corosio::read(stream, bufs);
239+
co_await capy::read(stream, bufs);
242240
243241
// Less efficient: may require more system calls
244-
co_await corosio::read(stream, buf1);
245-
co_await corosio::read(stream, buf2);
242+
co_await capy::read(stream, buf1);
243+
co_await capy::read(stream, buf2);
246244
----
247245

248246
=== Buffer Sizing
@@ -252,12 +250,12 @@ Choose buffer sizes that match your expected data:
252250
* Too small: More system calls
253251
* Too large: Memory waste
254252

255-
For unknown-length data (like HTTP responses), use the string overload:
253+
For unknown-length data (like HTTP responses), use the dynamic buffer overload:
256254

257255
[source,cpp]
258256
----
259257
std::string response;
260-
co_await corosio::read(stream, response); // Grows as needed
258+
co_await capy::read(stream, capy::string_dynamic_buffer(&response));
261259
----
262260

263261
== Example: HTTP Response Reading
@@ -267,11 +265,11 @@ co_await corosio::read(stream, response); // Grows as needed
267265
capy::task<std::string> read_http_response(corosio::io_stream& stream)
268266
{
269267
std::string response;
270-
auto [ec, n] = co_await corosio::read(stream, response);
268+
auto [ec, n] = co_await capy::read(
269+
stream, capy::string_dynamic_buffer(&response));
271270
272-
// EOF is expected when server closes connection
273-
if (ec && ec != capy::error::eof)
274-
throw boost::system::system_error(ec);
271+
if (ec)
272+
capy::detail::throw_system_error(ec);
275273
276274
co_return response;
277275
}

0 commit comments

Comments
 (0)