Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions doc/modules/ROOT/pages/8.examples/8c.buffer-composition.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Composing buffer sequences without allocation for scatter/gather I/O.
== What You Will Learn

* Creating buffers from different sources
* Using `const_buffer_pair` and `mutable_buffer_pair` for scatter/gather I/O
* Using `std::array<const_buffer, N>` and `std::array<mutable_buffer, N>` for scatter/gather I/O
* Zero-allocation buffer sequence patterns

== Prerequisites
Expand Down Expand Up @@ -44,15 +44,15 @@ void demonstrate_single_buffers()
std::cout << "Vector buffer: " << vec_buf.size() << " bytes\n";
}

void demonstrate_buffer_pair()
void demonstrate_two_buffer_scatter()
{
std::cout << "\n=== Buffer Pair (Scatter/Gather) ===\n\n";
// capy::const_buffer_pair is std::array<const_buffer, 2>
std::cout << "\n=== Two-Buffer Scatter/Gather ===\n\n";

// A 2-element buffer sequence is just a std::array
std::string header = "Content-Type: text/plain\r\n\r\n";
std::string body = "Hello, World!";
capy::const_buffer_pair message = {{

std::array<capy::const_buffer, 2> message = {{
capy::make_buffer(header),
capy::make_buffer(body)
}};
Expand Down Expand Up @@ -108,7 +108,7 @@ void demonstrate_mutable_buffers()
char buf1[64];
char buf2[64];

capy::mutable_buffer_pair recv_buffers = {{
std::array<capy::mutable_buffer, 2> recv_buffers = {{
capy::mutable_buffer(buf1, sizeof(buf1)),
capy::mutable_buffer(buf2, sizeof(buf2))
}};
Expand All @@ -124,7 +124,7 @@ void demonstrate_mutable_buffers()
int main()
{
demonstrate_single_buffers();
demonstrate_buffer_pair();
demonstrate_two_buffer_scatter();
demonstrate_buffer_array();
demonstrate_mutable_buffers();

Expand Down Expand Up @@ -152,17 +152,17 @@ auto arr_buf = capy::make_buffer(arr, sizeof(arr) - 1); // mutable_buffer

`make_buffer` creates buffer views from various sources. No data is copied—the buffers reference the original storage.

=== Buffer Pairs
=== Two-Buffer Scatter/Gather

[source,cpp]
----
capy::const_buffer_pair message = {{
std::array<capy::const_buffer, 2> message = {{
capy::make_buffer(header),
capy::make_buffer(body)
}};
----

`const_buffer_pair` is `std::array<const_buffer, 2>` a fixed-size buffer sequence for scatter/gather I/O. Similarly, `mutable_buffer_pair` holds two mutable buffers.
Capy's buffer-sequence concepts accept any range of `const_buffer` or `mutable_buffer`, so `std::array<X, 2>` is a buffer sequence with no further wrapping required. Use `mutable_buffer` for receive paths.

=== Multi-Buffer Arrays

Expand All @@ -175,7 +175,7 @@ std::array<capy::const_buffer, 5> http_response = {{
}};
----

For more than two buffers, use `std::array` directly. Buffer sequences support `buffer_size()` and `buffer_length()` for querying total bytes and buffer count.
For more than two buffers, the same pattern works with a larger `std::array`. Buffer sequences support `buffer_size()` and `buffer_length()` for querying total bytes and buffer count.

=== Scatter/Gather I/O

Expand All @@ -199,7 +199,7 @@ String buffer: 13 bytes
Array buffer: 10 bytes
Vector buffer: 6 bytes

=== Buffer Pair (Scatter/Gather) ===
=== Two-Buffer Scatter/Gather ===

Total message size: 41 bytes
Buffer count: 2
Expand Down
12 changes: 0 additions & 12 deletions doc/modules/ROOT/pages/9.design/9m.WhyNotCobalt.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,6 @@ Capy has one `DynamicBuffer` concept. The v1/v2 split in Asio exists because of
| Yes
|

| `buffer_pair`
| Yes
|

| `slice`
| Yes
|

| `front`
| Yes
|
Expand All @@ -449,10 +441,6 @@ Capy has one `DynamicBuffer` concept. The v1/v2 split in Asio exists because of
| Yes
|

| `buffer_array`
| Yes
|

| Byte-level trimming
| Yes
|
Expand Down
16 changes: 3 additions & 13 deletions doc/modules/ROOT/pages/why-capy.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Asio got buffer sequences right. The concept-driven approach—`ConstBufferSeque

Capy doesn't reinvent this. We adopt Asio's buffer sequence model because it works.

But we improve on it. Asio provides the basics; Capy extends them. Need to trim bytes from the front of a buffer sequence? Asio makes you work for it. Capy provides `buffer_slice` and `front`—byte-range slicing primitives for efficient byte-level manipulation. Need a circular buffer for protocol parsing? Capy has `circular_dynamic_buffer`. Need to compose two buffers without copying? `buffer_pair`.
But we improve on it. Asio provides the basics; Capy extends them. Need to trim bytes from the front of a buffer sequence? Asio makes you work for it. Capy provides `buffer_slice` and `front`—byte-range slicing primitives for efficient byte-level manipulation. Need a circular buffer for protocol parsing? Capy has `circular_dynamic_buffer`. Need to compose two buffers without copying? Use `std::array<const_buffer, 2>` (or any range of buffers) directly — Capy's buffer-sequence concepts accept arbitrary ranges.

And then there's the `DynamicBuffer` mess. If you've used Asio, you've encountered the confusing split between `DynamicBuffer_v1` and `DynamicBuffer_v2`. This exists because of a fundamental problem: when an async operation takes a buffer by value and completes via callback, who owns the buffer? The original design had flaws. The "fix" created two incompatible versions. (See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1100r0.html[P1100R0] for the full story.)

Expand All @@ -173,8 +173,8 @@ One more thing: `std::ranges` cannot help here. `ranges::size` returns the numbe
=== What Capy Offers

* `ConstBufferSequence`, `MutableBufferSequence`, `DynamicBuffer` — core concepts (Asio-compatible)
* `flat_dynamic_buffer`, `circular_dynamic_buffer`, `buffer_pair` — additional concrete types
* `buffer_slice`, `front`, `buffer_array` — byte-level manipulation utilities
* `flat_dynamic_buffer`, `circular_dynamic_buffer` — additional concrete buffer types
* `buffer_slice`, `front` — byte-level manipulation utilities

=== Comparison

Expand Down Expand Up @@ -227,11 +227,6 @@ One more thing: `std::ranges` cannot help here. `ranges::size` returns the numbe
|
|

| `buffer_pair`
|
|
|

| `buffer_slice`
|
|
Expand All @@ -247,11 +242,6 @@ One more thing: `std::ranges` cannot help here. `ranges::size` returns the numbe
|
|

| `buffer_array`
|
|
|

| `buffer_copy`
| `buffer_copy`
|
Expand Down
5 changes: 2 additions & 3 deletions example/asio/api/capy_streams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#include <boost/capy/buffers.hpp>
#include <boost/capy/buffers/asio.hpp>
#include <boost/capy/buffers/buffer_array.hpp>
#include <boost/capy/concept/stream.hpp>
#include <coroutine>
#include <boost/capy/ex/io_env.hpp>
Expand Down Expand Up @@ -108,7 +107,7 @@ class asio_socket
cancel_ = std::make_shared<cancel_state>(env->stop_token);

self_->socket_.async_read_some(
capy::to_asio(capy::mutable_buffer_array<8>(buffers_)),
capy::to_asio(buffers_),
net::bind_cancellation_slot(
cancel_->signal.slot(),
[this, ex = env->executor](
Expand Down Expand Up @@ -172,7 +171,7 @@ class asio_socket
cancel_ = std::make_shared<cancel_state>(env->stop_token);

self_->socket_.async_write_some(
capy::to_asio(capy::const_buffer_array<8>(buffers_)),
capy::to_asio(buffers_),
net::bind_cancellation_slot(
cancel_->signal.slot(),
[this, ex = env->executor](
Expand Down
14 changes: 7 additions & 7 deletions example/buffer-composition/buffer_composition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ void demonstrate_single_buffers()
std::cout << "Vector buffer: " << vec_buf.size() << " bytes\n";
}

void demonstrate_buffer_pair()
void demonstrate_two_buffer_scatter()
{
std::cout << "\n=== Buffer Pair (Scatter/Gather) ===\n\n";
std::cout << "\n=== Two-Buffer Scatter/Gather ===\n\n";

// capy::const_buffer_pair is std::array<const_buffer, 2>
// Two-element scatter/gather sequence (just a std::array)
std::string header = "Content-Type: text/plain\r\n\r\n";
std::string body = "Hello, World!";
capy::const_buffer_pair message = {{

std::array<capy::const_buffer, 2> message = {{
capy::make_buffer(header),
capy::make_buffer(body)
}};
Expand Down Expand Up @@ -98,7 +98,7 @@ void demonstrate_mutable_buffers()
char buf1[64];
char buf2[64];

capy::mutable_buffer_pair recv_buffers = {{
std::array<capy::mutable_buffer, 2> recv_buffers = {{
capy::mutable_buffer(buf1, sizeof(buf1)),
capy::mutable_buffer(buf2, sizeof(buf2))
}};
Expand All @@ -114,7 +114,7 @@ void demonstrate_mutable_buffers()
int main()
{
demonstrate_single_buffers();
demonstrate_buffer_pair();
demonstrate_two_buffer_scatter();
demonstrate_buffer_array();
demonstrate_mutable_buffers();

Expand Down
3 changes: 0 additions & 3 deletions include/boost/capy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,12 @@
// Buffers
#include <boost/capy/buffers.hpp>
#include <boost/capy/buffers/buffer_copy.hpp>
#include <boost/capy/buffers/buffer_pair.hpp>
#include <boost/capy/buffers/buffer_param.hpp>
#include <boost/capy/buffers/buffer_slice.hpp>
#include <boost/capy/buffers/circular_dynamic_buffer.hpp>
#include <boost/capy/buffers/flat_dynamic_buffer.hpp>
#include <boost/capy/buffers/front.hpp>
#include <boost/capy/buffers/make_buffer.hpp>
#include <boost/capy/buffers/slice.hpp>
#include <boost/capy/buffers/buffer_array.hpp>
#include <boost/capy/buffers/string_dynamic_buffer.hpp>
#include <boost/capy/buffers/vector_dynamic_buffer.hpp>

Expand Down
Loading
Loading