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
14 changes: 7 additions & 7 deletions doc/modules/ROOT/pages/7.examples/7a.hello-task.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ The minimal Capy program: a task that prints a message.
#include <boost/capy.hpp>
#include <iostream>

using namespace boost::capy;
namespace capy = boost::capy;

task<> say_hello()
capy::task<> say_hello()
{
std::cout << "Hello from Capy!\n";
co_return;
}

int main()
{
thread_pool pool;
run_async(pool.get_executor())(say_hello());
capy::thread_pool pool;
capy::run_async(pool.get_executor())(say_hello());
return 0;
}
----
Expand All @@ -50,7 +50,7 @@ target_link_libraries(hello_task PRIVATE capy)

[source,cpp]
----
task<> say_hello()
capy::task<> say_hello()
{
std::cout << "Hello from Capy!\n";
co_return;
Expand All @@ -65,7 +65,7 @@ Tasks are lazy: calling `say_hello()` creates a task object but does not execute

[source,cpp]
----
thread_pool pool;
capy::thread_pool pool;
----

`thread_pool` provides an execution context with worker threads. By default, it creates one thread per CPU core.
Expand All @@ -76,7 +76,7 @@ The pool's destructor waits for all work to complete before returning. This ensu

[source,cpp]
----
run_async(pool.get_executor())(say_hello());
capy::run_async(pool.get_executor())(say_hello());
----

`run_async` bridges non-coroutine code (like `main`) to coroutine code. The two-call syntax:
Expand Down
46 changes: 24 additions & 22 deletions doc/modules/ROOT/pages/7.examples/7b.producer-consumer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,44 @@ Two tasks communicating via an async event, with strand serialization.
#include <iostream>
#include <latch>

using namespace boost::capy;
namespace capy = boost::capy;

int main()
{
thread_pool pool; // thread_pool
strand s{pool.get_executor()}; // strand - serializes execution
std::latch done(1); // std::latch - wait for completion
capy::thread_pool pool;
capy::strand s{pool.get_executor()};
std::latch done(1);

auto on_complete = [&done](auto&&...) { done.count_down(); }; // lambda
auto on_error = [&done](std::exception_ptr) { done.count_down(); }; // lambda
auto on_complete = [&done](auto&&...) { done.count_down(); };
auto on_error = [&done](std::exception_ptr) { done.count_down(); };

async_event data_ready; // async_event
int shared_value = 0; // int
capy::async_event data_ready;
int shared_value = 0;

auto producer = [&]() -> task<> {
auto producer = [&]() -> capy::task<> {
std::cout << "Producer: preparing data...\n";
shared_value = 42;
std::cout << "Producer: data ready, signaling\n";
data_ready.set();
co_return;
};

auto consumer = [&]() -> task<> {
auto consumer = [&]() -> capy::task<> {
std::cout << "Consumer: waiting for data...\n";
co_await data_ready.wait();
auto [ec] = co_await data_ready.wait();
(void)ec;
std::cout << "Consumer: received value " << shared_value << "\n";
co_return;
};

// Run both tasks concurrently using when_all, through a strand.
// The strand serializes execution, ensuring thread-safe access
// to the shared async_event and shared_value.
auto run_both = [&]() -> task<> {
co_await when_all(producer(), consumer());
auto run_both = [&]() -> capy::task<> {
co_await capy::when_all(producer(), consumer());
};

run_async(s, on_complete, on_error)(run_both());
capy::run_async(s, on_complete, on_error)(run_both());

done.wait(); // Block until tasks complete
return 0;
Expand All @@ -80,7 +81,7 @@ target_link_libraries(producer_consumer PRIVATE capy)

[source,cpp]
----
strand s{pool.get_executor()}; // strand - serializes execution
capy::strand s{pool.get_executor()};
----

A `strand` is an executor adaptor that serializes execution. All coroutines dispatched through a strand are guaranteed not to run concurrently, making it safe to access shared state without explicit locking. Note that `async_event` is not thread-safe, so using a strand ensures safe access.
Expand All @@ -89,7 +90,7 @@ A `strand` is an executor adaptor that serializes execution. All coroutines disp

[source,cpp]
----
async_event data_ready; // async_event
capy::async_event data_ready;
----

`async_event` is a one-shot signaling mechanism. One task can `set()` it; other tasks can `wait()` for it. When set, all waiting tasks resume.
Expand All @@ -98,7 +99,7 @@ async_event data_ready; // async_event

[source,cpp]
----
auto producer = [&]() -> task<> {
auto producer = [&]() -> capy::task<> {
std::cout << "Producer: preparing data...\n";
shared_value = 42;
std::cout << "Producer: data ready, signaling\n";
Expand All @@ -113,9 +114,10 @@ The producer prepares data and signals completion by calling `set()`.

[source,cpp]
----
auto consumer = [&]() -> task<> {
auto consumer = [&]() -> capy::task<> {
std::cout << "Consumer: waiting for data...\n";
co_await data_ready.wait();
auto [ec] = co_await data_ready.wait();
(void)ec;
std::cout << "Consumer: received value " << shared_value << "\n";
co_return;
};
Expand All @@ -130,11 +132,11 @@ The consumer waits until the event is set. The `co_await data_ready.wait()` susp
// Run both tasks concurrently using when_all, through a strand.
// The strand serializes execution, ensuring thread-safe access
// to the shared async_event and shared_value.
auto run_both = [&]() -> task<> {
co_await when_all(producer(), consumer());
auto run_both = [&]() -> capy::task<> {
co_await capy::when_all(producer(), consumer());
};

run_async(s, on_complete, on_error)(run_both());
capy::run_async(s, on_complete, on_error)(run_both());
----

`when_all` runs both tasks concurrently within the same parent coroutine context, but the strand ensures they don't run at the same time on different threads. The producer signals `data_ready` when the value is set, and the consumer waits for the signal before reading.
Expand Down
62 changes: 31 additions & 31 deletions doc/modules/ROOT/pages/7.examples/7c.buffer-composition.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Composing buffer sequences without allocation for scatter/gather I/O.
#include <array>
#include <vector>

using namespace boost::capy;
namespace capy = boost::capy;

void demonstrate_single_buffers()
{
Expand All @@ -35,9 +35,9 @@ void demonstrate_single_buffers()
std::vector<char> vec = {'V', 'e', 'c', 't', 'o', 'r'};

// make_buffer creates buffer views (no copies)
auto str_buf = make_buffer(str); // mutable_buffer
auto arr_buf = make_buffer(arr, sizeof(arr) - 1); // mutable_buffer - Exclude null terminator
auto vec_buf = make_buffer(vec); // mutable_buffer
auto str_buf = capy::make_buffer(str); // mutable_buffer
auto arr_buf = capy::make_buffer(arr, sizeof(arr) - 1); // mutable_buffer - Exclude null terminator
auto vec_buf = capy::make_buffer(vec); // mutable_buffer

std::cout << "String buffer: " << str_buf.size() << " bytes\n";
std::cout << "Array buffer: " << arr_buf.size() << " bytes\n";
Expand All @@ -48,19 +48,19 @@ void demonstrate_buffer_pair()
{
std::cout << "\n=== Buffer Pair (Scatter/Gather) ===\n\n";

// const_buffer_pair is std::array<const_buffer, 2>
// capy::const_buffer_pair is std::array<const_buffer, 2>
std::string header = "Content-Type: text/plain\r\n\r\n";
std::string body = "Hello, World!";

const_buffer_pair message = {{
make_buffer(header),
make_buffer(body)
capy::const_buffer_pair message = {{
capy::make_buffer(header),
capy::make_buffer(body)
}};

// Calculate total size
std::size_t total = buffer_size(message);
std::size_t total = capy::buffer_size(message);
std::cout << "Total message size: " << total << " bytes\n";
std::cout << "Buffer count: " << buffer_length(message) << "\n";
std::cout << "Buffer count: " << capy::buffer_length(message) << "\n";

// Iterate through buffers
std::cout << "\nBuffer contents:\n";
Expand All @@ -83,17 +83,17 @@ void demonstrate_buffer_array()
std::string empty_line = "\r\n";
std::string body = R"({"status":"ok"})";

std::array<const_buffer, 5> http_response = {{
make_buffer(status),
make_buffer(content_type),
make_buffer(server),
make_buffer(empty_line),
make_buffer(body)
std::array<capy::const_buffer, 5> http_response = {{
capy::make_buffer(status),
capy::make_buffer(content_type),
capy::make_buffer(server),
capy::make_buffer(empty_line),
capy::make_buffer(body)
}};

std::size_t total = buffer_size(http_response);
std::size_t total = capy::buffer_size(http_response);
std::cout << "HTTP response size: " << total << " bytes\n";
std::cout << "Buffer count: " << buffer_length(http_response) << "\n";
std::cout << "Buffer count: " << capy::buffer_length(http_response) << "\n";

// In real code with streams:
// co_await write(stream, http_response);
Expand All @@ -108,13 +108,13 @@ void demonstrate_mutable_buffers()
char buf1[64];
char buf2[64];

mutable_buffer_pair recv_buffers = {{
mutable_buffer(buf1, sizeof(buf1)),
mutable_buffer(buf2, sizeof(buf2))
capy::mutable_buffer_pair recv_buffers = {{
capy::mutable_buffer(buf1, sizeof(buf1)),
capy::mutable_buffer(buf2, sizeof(buf2))
}};

std::cout << "Prepared " << buffer_length(recv_buffers)
<< " buffers with " << buffer_size(recv_buffers)
std::cout << "Prepared " << capy::buffer_length(recv_buffers)
<< " buffers with " << capy::buffer_size(recv_buffers)
<< " bytes total capacity\n";

// In real code:
Expand Down Expand Up @@ -146,8 +146,8 @@ target_link_libraries(buffer_composition PRIVATE capy)

[source,cpp]
----
auto str_buf = make_buffer(str); // mutable_buffer
auto arr_buf = make_buffer(arr, sizeof(arr) - 1); // mutable_buffer
auto str_buf = capy::make_buffer(str); // mutable_buffer
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.
Expand All @@ -156,9 +156,9 @@ auto arr_buf = make_buffer(arr, sizeof(arr) - 1); // mutable_buffer

[source,cpp]
----
const_buffer_pair message = {{
make_buffer(header),
make_buffer(body)
capy::const_buffer_pair message = {{
capy::make_buffer(header),
capy::make_buffer(body)
}};
----

Expand All @@ -168,9 +168,9 @@ const_buffer_pair message = {{

[source,cpp]
----
std::array<const_buffer, 5> http_response = {{
make_buffer(status),
make_buffer(content_type),
std::array<capy::const_buffer, 5> http_response = {{
capy::make_buffer(status),
capy::make_buffer(content_type),
// ...
}};
----
Expand Down
Loading
Loading