diff --git a/_ b/_ new file mode 120000 index 0000000..46322eb --- /dev/null +++ b/_ @@ -0,0 +1 @@ +preview/_ \ No newline at end of file diff --git a/preview/2.cpp20-coroutines/2.intro.html b/preview/2.cpp20-coroutines/2.intro.html new file mode 100644 index 0000000..4d5eb31 --- /dev/null +++ b/preview/2.cpp20-coroutines/2.intro.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + Introduction To C++20 Coroutines :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Introduction To C++20 Coroutines

+
+

Every C++ function you have ever written follows the same contract: it runs from start to finish, then returns. The caller waits. The stack frame lives and dies in lockstep with that single invocation. This model has served us well for decades, but it forces a hard tradeoff when programs need to wait—​for a network response, a disk read, a timer, or another thread. The function either blocks (wasting a thread) or you restructure your code into callbacks, state machines, or futures that scatter your logic across multiple places.

+
+
+

C++20 coroutines change the rules. A coroutine can suspend its execution—​saving its local state somewhere outside the stack—​and resume later, picking up exactly where it left off. The control flow reads top-to-bottom, like the synchronous code you already know, but the runtime behavior is asynchronous. No blocked threads. No callback chains. No lost context.

+
+
+

This is not a minor syntactic convenience. It is a fundamental shift in how you can structure programs that wait.

+
+
+

This section takes you from zero to a working understanding of C++20 coroutines. No prior experience with coroutines or async programming is needed. You will start with the problem that coroutines solve, move through the language syntax and compiler machinery, and finish with the performance characteristics that make coroutines practical for real systems. By the end, you will understand not only how to write coroutines but why they work the way they do—​knowledge that will make everything in the rest of this documentation click into place.

+
+ + +
+
+ +
+ + diff --git a/preview/2.cpp20-coroutines/2a.foundations.html b/preview/2.cpp20-coroutines/2a.foundations.html new file mode 100644 index 0000000..c31de59 --- /dev/null +++ b/preview/2.cpp20-coroutines/2a.foundations.html @@ -0,0 +1,615 @@ + + + + + + + + + + + + + + Part I: Foundations :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part I: Foundations

+
+
+
+

This section introduces the fundamental concepts you need before working with C++20 coroutines. You will learn how normal functions work, what makes coroutines different, and why coroutines exist as a language feature.

+
+
+
+
+

Prerequisites

+
+
+

Before beginning this tutorial, you should have:

+
+
+
    +
  • +

    A C++ compiler with C++20 support (GCC 10+, Clang 14+, or MSVC 2019 16.8+)

    +
  • +
  • +

    Familiarity with basic C++ concepts: functions, classes, templates, and lambdas

    +
  • +
  • +

    Understanding of how function calls work: the call stack, local variables, and return values

    +
  • +
+
+
+

The examples in this tutorial use standard C++20 features. Compile with:

+
+
+
    +
  • +

    GCC: g -std=c20 -fcoroutines your_file.cpp

    +
  • +
  • +

    Clang: clang -std=c20 your_file.cpp

    +
  • +
  • +

    MSVC: cl /std:c++20 your_file.cpp

    +
  • +
+
+
+
+
+

Functions and the Call Stack

+
+
+

When you call a regular function, the system allocates space on the call stack for the function’s local variables and parameters. This stack space is called a stack frame. When the function returns, this stack space is reclaimed. The function’s state exists only during the call.

+
+
+

Consider this function:

+
+
+
+
int compute(int x, int y)
+{
+    int result = x * y + 42;
+    return result;
+}
+
+
+
+

When compute is called:

+
+
+
    +
  1. +

    A stack frame is allocated containing x, y, and result

    +
  2. +
  3. +

    The function body executes

    +
  4. +
  5. +

    The return value is passed back to the caller

    +
  6. +
  7. +

    The stack frame is deallocated

    +
  8. +
+
+
+

This model has a fundamental constraint: run-to-completion. Once a function starts, it must finish before control returns to the caller. The function cannot pause midway, let other code run, and resume later.

+
+
+
+
+

What Is a Coroutine?

+
+
+

A coroutine is a function that can suspend its execution and resume later from exactly where it left off. Think of it as a bookmark in a book of instructions—instead of reading the entire book in one sitting, you can mark your place, do something else, and return to continue reading.

+
+
+

When a coroutine suspends:

+
+
+
    +
  • +

    Its local variables are preserved

    +
  • +
  • +

    The instruction pointer (where you are in the code) is saved

    +
  • +
  • +

    Control returns to the caller or some other code

    +
  • +
+
+
+

When a coroutine resumes:

+
+
+
    +
  • +

    Local variables are restored to their previous values

    +
  • +
  • +

    Execution continues from the suspension point

    +
  • +
+
+
+

This capability is implemented through a coroutine frame—a heap-allocated block of memory that stores the coroutine’s state. Unlike stack frames, coroutine frames persist across suspension points because they live on the heap rather than the stack.

+
+
+
+
// Conceptual illustration (not real syntax)
+task<int> fetch_and_process()
+{
+    auto data = co_await fetch_from_network();  // suspends here
+    // When resumed, 'data' contains the fetched result
+    return process(data);
+}
+
+
+
+

The variable data maintains its value even though the function may have suspended and resumed. This is the fundamental capability that coroutines provide.

+
+
+
+
+

Why Coroutines?

+
+
+

The Problem: Asynchronous Programming Without Coroutines

+
+

Consider a server application that handles network requests. The server must read a request, query a database, compute a response, and send it back. Each step might take time to complete.

+
+
+

In traditional synchronous code:

+
+
+
+
void handle_request(connection& conn)
+{
+    std::string request = conn.read();      // blocks until data arrives
+    auto parsed = parse_request(request);
+    auto data = database.query(parsed.id);  // blocks until database responds
+    auto response = compute_response(data);
+    conn.write(response);                   // blocks until write completes
+}
+
+
+
+

This code reads naturally from top to bottom. But while waiting for the network or database, this function blocks the entire thread. If you have thousands of concurrent connections, you would need thousands of threads, each consuming memory and requiring operating system scheduling.

+
+
+
+

The Callback Approach

+
+

The traditional solution uses callbacks:

+
+
+
+
void handle_request(connection& conn)
+{
+    conn.async_read([&conn](std::string request) {
+        auto parsed = parse_request(request);
+        database.async_query(parsed.id, [&conn](auto data) {
+            auto response = compute_response(data);
+            conn.async_write(response, [&conn]() {
+                // request complete
+            });
+        });
+    });
+}
+
+
+
+

This code does not block. Each operation starts, registers a callback, and returns immediately. When the operation completes, the callback runs.

+
+
+

But look what has happened to the code: three levels of nesting, logic scattered across multiple lambda functions, and local variables that cannot be shared between callbacks without careful lifetime management. A single logical operation becomes fragmented across multiple functions.

+
+
+
+

The Coroutine Solution

+
+

Coroutines restore linear code structure while maintaining asynchronous behavior:

+
+
+
+
task<void> handle_request(connection& conn)
+{
+    std::string request = co_await conn.async_read();
+    auto parsed = parse_request(request);
+    auto data = co_await database.async_query(parsed.id);
+    auto response = compute_response(data);
+    co_await conn.async_write(response);
+}
+
+
+
+

This code reads like the original blocking version. Local variables like request, parsed, and data exist naturally in their scope. Yet the function suspends at each co_await point, allowing other work to proceed while waiting.

+
+
+
+

Beyond Asynchrony

+
+

Coroutines also enable:

+
+
+
    +
  • +

    Generators — Functions that produce sequences of values on demand, computing each value only when requested

    +
  • +
  • +

    State machines — Complex control flow expressed as linear code with suspension points

    +
  • +
  • +

    Cooperative multitasking — Multiple logical tasks interleaved on a single thread

    +
  • +
+
+
+

You have now learned what coroutines are and why they exist. In the next section, you will learn the C++20 syntax for creating coroutines.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/2.cpp20-coroutines/2b.syntax.html b/preview/2.cpp20-coroutines/2b.syntax.html new file mode 100644 index 0000000..853f2fd --- /dev/null +++ b/preview/2.cpp20-coroutines/2b.syntax.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + + Part II: C++20 Syntax :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part II: C++20 Syntax

+
+
+
+

This section introduces the three C++20 keywords that create coroutines and walks you through building your first coroutine step by step.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Part I: Foundations

    +
  • +
  • +

    Understanding of why coroutines exist and what problem they solve

    +
  • +
+
+
+
+
+

The Three Keywords

+
+
+

A function becomes a coroutine when its body contains any of three special keywords: co_await, co_yield, or co_return. The presence of any of these keywords signals to the compiler that the function requires coroutine machinery.

+
+
+

co_await

+
+

The co_await keyword suspends the coroutine and waits for some operation to complete. When you write co_await expr, the coroutine saves its state, pauses execution, and potentially allows other code to run. When the awaited operation completes, the coroutine resumes from exactly where it left off.

+
+
+
+
task<std::string> fetch_page(std::string url)
+{
+    auto response = co_await http_get(url);  // suspends until HTTP completes
+    return response.body;                     // continues after resumption
+}
+
+
+
+
+

co_yield

+
+

The co_yield keyword produces a value and suspends the coroutine. This pattern creates generators—functions that produce sequences of values one at a time. After yielding a value, the coroutine pauses until someone asks for the next value.

+
+
+
+
generator<int> count_to(int n)
+{
+    for (int i = 1; i <= n; ++i)
+    {
+        co_yield i;  // produce value, suspend, resume when next value requested
+    }
+}
+
+
+
+
+

co_return

+
+

The co_return keyword completes the coroutine and optionally provides a final result. Unlike a regular return statement, co_return interacts with the coroutine machinery to properly finalize the coroutine’s state.

+
+
+
+
task<int> compute()
+{
+    int result = 42;
+    co_return result;  // completes the coroutine with value 42
+}
+
+
+
+

For coroutines that do not return a value, use co_return; without an argument.

+
+
+
+
+
+

Your First Coroutine

+
+
+

The distinction between regular functions and coroutines matters because they behave fundamentally differently at runtime:

+
+
+
    +
  • +

    A regular function allocates its local variables on the stack. When it returns, those variables are gone.

    +
  • +
  • +

    A coroutine allocates its local variables in a heap-allocated coroutine frame. When it suspends, those variables persist. When it resumes, they are still there.

    +
  • +
+
+
+

Here is the minimal structure needed to create a coroutine:

+
+
+
+
#include <coroutine>
+
+struct SimpleCoroutine
+{
+    struct promise_type
+    {
+        SimpleCoroutine get_return_object() { return {}; }
+        std::suspend_never initial_suspend() { return {}; }
+        std::suspend_never final_suspend() noexcept { return {}; }
+        void return_void() {}
+        void unhandled_exception() {}
+    };
+};
+
+SimpleCoroutine my_first_coroutine()
+{
+    co_return;  // This makes it a coroutine
+}
+
+
+
+

The promise_type nested structure provides the minimum scaffolding the compiler needs. You will learn what each method does in Part III: Coroutine Machinery.

+
+
+

For now, observe that the presence of co_return transforms what looks like a regular function into a coroutine. If you try to compile a function with coroutine keywords but without proper infrastructure, the compiler will produce errors.

+
+
+
+
+

Awaitables and Awaiters

+
+
+

When you write co_await expr, the expression expr must be an awaitable—something that knows how to suspend and resume a coroutine. The awaitable produces an awaiter object that implements three methods:

+
+
+
    +
  • +

    await_ready() — Returns true if the result is immediately available and no suspension is needed

    +
  • +
  • +

    await_suspend(handle) — Called when the coroutine suspends; receives a handle to the coroutine for later resumption

    +
  • +
  • +

    await_resume() — Called when the coroutine resumes; its return value becomes the value of the co_await expression

    +
  • +
+
+
+

Example: Understanding the Awaiter Protocol

+
+
+
#include <coroutine>
+#include <iostream>
+
+struct ReturnObject
+{
+    struct promise_type
+    {
+        ReturnObject get_return_object() { return {}; }
+        std::suspend_never initial_suspend() { return {}; }
+        std::suspend_never final_suspend() noexcept { return {}; }
+        void return_void() {}
+        void unhandled_exception() {}
+    };
+};
+
+struct Awaiter
+{
+    std::coroutine_handle<>* handle_out;
+
+    bool await_ready() { return false; }  // always suspend
+
+    void await_suspend(std::coroutine_handle<> h)
+    {
+        *handle_out = h;  // store handle for later resumption
+    }
+
+    void await_resume() {}  // nothing to return
+};
+
+ReturnObject counter(std::coroutine_handle<>* handle)
+{
+    Awaiter awaiter{handle};
+
+    for (unsigned i = 0; ; ++i)
+    {
+        std::cout << "counter: " << i << std::endl;
+        co_await awaiter;
+    }
+}
+
+int main()
+{
+    std::coroutine_handle<> h;
+    counter(&h);
+
+    for (int i = 0; i < 3; ++i)
+    {
+        std::cout << "main: resuming" << std::endl;
+        h();
+    }
+
+    h.destroy();
+}
+
+
+
+

Output:

+
+
+
+
counter: 0
+main: resuming
+counter: 1
+main: resuming
+counter: 2
+main: resuming
+counter: 3
+
+
+
+

Study this execution flow:

+
+
+
    +
  1. +

    main calls counter, passing the address of a coroutine handle

    +
  2. +
  3. +

    counter begins executing, prints "counter: 0", and reaches co_await awaiter

    +
  4. +
  5. +

    await_ready() returns false, so suspension proceeds

    +
  6. +
  7. +

    await_suspend receives a handle to the suspended coroutine and stores it in main’s variable `h

    +
  8. +
  9. +

    Control returns to main, which now holds a handle to the suspended coroutine

    +
  10. +
  11. +

    main calls h(), which resumes the coroutine

    +
  12. +
  13. +

    The coroutine continues from where it left off, increments i, prints "counter: 1", and suspends again

    +
  14. +
  15. +

    This cycle repeats until main destroys the coroutine

    +
  16. +
+
+
+

The variable i inside counter maintains its value across all these suspension and resumption cycles.

+
+
+
+

Standard Awaiters

+
+

The C++ standard library provides two predefined awaiters:

+
+
+
    +
  • +

    std::suspend_alwaysawait_ready() returns false (always suspend)

    +
  • +
  • +

    std::suspend_neverawait_ready() returns true (never suspend)

    +
  • +
+
+
+

These are useful building blocks for promise types and custom awaitables.

+
+
+
+
// suspend_always causes suspension at this point
+co_await std::suspend_always{};
+
+// suspend_never continues immediately without suspending
+co_await std::suspend_never{};
+
+
+
+

You have now learned the three coroutine keywords and how awaitables work. In the next section, you will learn about the promise type and coroutine handle—the machinery that makes coroutines function.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/2.cpp20-coroutines/2c.machinery.html b/preview/2.cpp20-coroutines/2c.machinery.html new file mode 100644 index 0000000..2f840f0 --- /dev/null +++ b/preview/2.cpp20-coroutines/2c.machinery.html @@ -0,0 +1,840 @@ + + + + + + + + + + + + + + Part III: Coroutine Machinery :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part III: Coroutine Machinery

+
+
+
+

This section explains the promise type and coroutine handle—the core machinery that controls coroutine behavior. You will build a complete generator type by understanding how these pieces work together.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Part II: C++20 Syntax

    +
  • +
  • +

    Understanding of the three coroutine keywords

    +
  • +
  • +

    Familiarity with awaitables and awaiters

    +
  • +
+
+
+
+
+

The Promise Type

+
+
+

Every coroutine has an associated promise type. This type acts as a controller for the coroutine, defining how it behaves at key points in its lifecycle. The promise type is not something you pass to the coroutine—it is a nested type inside the coroutine’s return type that the compiler uses automatically.

+
+
+

The compiler expects to find a type named promise_type nested inside your coroutine’s return type. If your coroutine returns Generator<int>, the compiler looks for Generator<int>::promise_type.

+
+
+

Required Methods

+
+

The promise type must provide these methods:

+
+
+
+
get_return_object()
+
+

Called to create the object that will be returned to the caller of the coroutine. This happens before the coroutine body begins executing.

+
+
initial_suspend()
+
+

Called immediately after get_return_object(). Returns an awaiter that determines whether the coroutine should suspend before running any of its body. Return std::suspend_never{} to start executing immediately, or std::suspend_always{} to suspend before the first statement.

+
+
final_suspend()
+
+

Called when the coroutine completes (either normally or via exception). Returns an awaiter that determines whether to suspend one last time or destroy the coroutine state immediately. This method must be noexcept.

+
+
return_void() or return_value(v)
+
+

Called when the coroutine executes co_return or falls off the end of its body. Use return_void() if the coroutine does not return a value; use return_value(v) if it does. You must provide exactly one of these, matching how your coroutine returns.

+
+
unhandled_exception()
+
+

Called if an exception escapes the coroutine body. Typically you either rethrow the exception, store it for later, or terminate the program.

+
+
+
+
+
+

The Compiler Transformation

+
+

The compiler transforms your coroutine body into something resembling this pseudocode:

+
+
+
+
{
+    promise_type promise;
+    auto return_object = promise.get_return_object();
+
+    co_await promise.initial_suspend();
+
+    try {
+        // your coroutine body goes here
+    }
+    catch (...) {
+        promise.unhandled_exception();
+    }
+
+    co_await promise.final_suspend();
+}
+// coroutine frame is destroyed when control flows off the end
+
+
+
+

Important observations:

+
+
+
    +
  • +

    The return object is created before initial_suspend() runs, so it is available even if the coroutine suspends immediately

    +
  • +
  • +

    final_suspend() determines whether the coroutine frame persists after completion—if it returns suspend_always, you must manually destroy the coroutine; if it returns suspend_never, the frame is destroyed automatically

    +
  • +
+
+
+
+

Tracing Promise Behavior

+
+
+
#include <coroutine>
+#include <iostream>
+
+struct TracePromise
+{
+    struct promise_type
+    {
+        promise_type()
+        {
+            std::cout << "promise constructed" << std::endl;
+        }
+
+        ~promise_type()
+        {
+            std::cout << "promise destroyed" << std::endl;
+        }
+
+        TracePromise get_return_object()
+        {
+            std::cout << "get_return_object called" << std::endl;
+            return {};
+        }
+
+        std::suspend_never initial_suspend()
+        {
+            std::cout << "initial_suspend called" << std::endl;
+            return {};
+        }
+
+        std::suspend_always final_suspend() noexcept
+        {
+            std::cout << "final_suspend called" << std::endl;
+            return {};
+        }
+
+        void return_void()
+        {
+            std::cout << "return_void called" << std::endl;
+        }
+
+        void unhandled_exception()
+        {
+            std::cout << "unhandled_exception called" << std::endl;
+        }
+    };
+};
+
+TracePromise trace_coroutine()
+{
+    std::cout << "coroutine body begins" << std::endl;
+    co_return;
+}
+
+int main()
+{
+    std::cout << "calling coroutine" << std::endl;
+    auto result = trace_coroutine();
+    std::cout << "coroutine returned" << std::endl;
+}
+
+
+
+

Output:

+
+
+
+
calling coroutine
+promise constructed
+get_return_object called
+initial_suspend called
+coroutine body begins
+return_void called
+final_suspend called
+coroutine returned
+
+
+
+

Notice that the promise is constructed first, then get_return_object() creates the return value, then initial_suspend() runs. Since initial_suspend() returns suspend_never, the coroutine body executes immediately. After co_return, return_void() is called, followed by final_suspend(). Since final_suspend() returns suspend_always, the coroutine suspends one last time, and the promise is not destroyed until the coroutine handle is explicitly destroyed.

+
+
+ + + + + +
+ + +
+

If your coroutine can fall off the end of its body without executing co_return, and your promise type lacks a return_void() method, the behavior is undefined. Always ensure your promise type has return_void() if there is any code path that might reach the end of the coroutine body without an explicit co_return.

+
+
+
+
+
+
+
+

Coroutine Handle

+
+
+

A std::coroutine_handle<> is a lightweight object that refers to a suspended coroutine. It is similar to a pointer: it does not own the memory it references, and copying it does not copy the coroutine.

+
+
+

Basic Operations

+
+
    +
  • +

    handle() or handle.resume() — Resume the coroutine

    +
  • +
  • +

    handle.done() — Returns true if the coroutine has completed

    +
  • +
  • +

    handle.destroy() — Destroy the coroutine frame (frees memory)

    +
  • +
  • +

    handle.promise() — Returns a reference to the promise object (typed handles only)

    +
  • +
+
+
+
+

Typed vs Untyped Handles

+
+
+
std::coroutine_handle<>
+
+

The most basic form (equivalent to std::coroutine_handle<void>). Can reference any coroutine but provides no access to the promise object.

+
+
std::coroutine_handle<PromiseType>
+
+

A typed handle that knows about a particular promise type. Can be converted to the void handle. Provides a promise() method that returns a reference to the promise object.

+
+
+
+
+
+

Creating Handles from Promises

+
+

Inside get_return_object(), you can obtain the coroutine handle using:

+
+
+
+
std::coroutine_handle<promise_type>::from_promise(*this)
+
+
+
+

Since get_return_object() is called on the promise object (as this), this method returns a handle to the coroutine containing that promise.

+
+
+
+
+
+

Putting It Together: Building a Generator

+
+
+

A generator is a function that produces a sequence of values on demand. Instead of computing all values upfront, a generator computes each value when requested using co_yield.

+
+
+

How co_yield Works

+
+

The expression co_yield value is transformed by the compiler into:

+
+
+
+
co_await promise.yield_value(value)
+
+
+
+

The yield_value method receives the yielded value, stores it somewhere accessible, and returns an awaiter (usually std::suspend_always) to suspend the coroutine.

+
+
+
+

Complete Generator Implementation

+
+
+
#include <coroutine>
+#include <iostream>
+
+struct Generator
+{
+    struct promise_type
+    {
+        int current_value;
+
+        Generator get_return_object()
+        {
+            return Generator{
+                std::coroutine_handle<promise_type>::from_promise(*this)
+            };
+        }
+
+        std::suspend_always initial_suspend() { return {}; }
+        std::suspend_always final_suspend() noexcept { return {}; }
+
+        std::suspend_always yield_value(int value)
+        {
+            current_value = value;
+            return {};
+        }
+
+        void return_void() {}
+        void unhandled_exception() { std::terminate(); }
+    };
+
+    std::coroutine_handle<promise_type> handle;
+
+    Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
+
+    ~Generator()
+    {
+        if (handle)
+            handle.destroy();
+    }
+
+    // Disable copying
+    Generator(Generator const&) = delete;
+    Generator& operator=(Generator const&) = delete;
+
+    // Enable moving
+    Generator(Generator&& other) noexcept
+        : handle(other.handle)
+    {
+        other.handle = nullptr;
+    }
+
+    Generator& operator=(Generator&& other) noexcept
+    {
+        if (this != &other)
+        {
+            if (handle)
+                handle.destroy();
+            handle = other.handle;
+            other.handle = nullptr;
+        }
+        return *this;
+    }
+
+    bool next()
+    {
+        if (!handle || handle.done())
+            return false;
+        handle.resume();
+        return !handle.done();
+    }
+
+    int value() const
+    {
+        return handle.promise().current_value;
+    }
+};
+
+Generator count_to(int n)
+{
+    for (int i = 1; i <= n; ++i)
+    {
+        co_yield i;
+    }
+}
+
+int main()
+{
+    auto gen = count_to(5);
+
+    while (gen.next())
+    {
+        std::cout << gen.value() << std::endl;
+    }
+}
+
+
+
+

Output:

+
+
+
+
1
+2
+3
+4
+5
+
+
+
+
+

Key Design Decisions

+
+
+
initial_suspend() returns suspend_always
+
+

The coroutine suspends before running any user code. This means the first call to next() starts the coroutine running.

+
+
final_suspend() returns suspend_always
+
+

The coroutine frame persists after completion. This is necessary because the iterator needs to check handle.done() after the last value.

+
+
Generator owns the handle
+
+

The destructor calls handle.destroy() to free the coroutine frame. Copying is disabled to avoid double-free; moving transfers ownership.

+
+
yield_value stores and suspends
+
+

Stores the yielded value in current_value and returns suspend_always to pause the coroutine after each yield.

+
+
+
+
+
+

Fibonacci Generator

+
+

Here is a more interesting generator that produces the Fibonacci sequence:

+
+
+
+
Generator fibonacci()
+{
+    int a = 0, b = 1;
+    while (true)
+    {
+        co_yield a;
+        int next = a + b;
+        a = b;
+        b = next;
+    }
+}
+
+int main()
+{
+    auto fib = fibonacci();
+
+    for (int i = 0; i < 10 && fib.next(); ++i)
+    {
+        std::cout << fib.value() << " ";
+    }
+    std::cout << std::endl;
+}
+
+
+
+

Output:

+
+
+
+
0 1 1 2 3 5 8 13 21 34
+
+
+
+

The Fibonacci generator runs an infinite loop internally. It will produce values forever. But because it yields and suspends after each value, the caller controls when (and whether) to ask for more values. The generator only computes values on demand.

+
+
+

The variables a and b persist across yields because they live in the coroutine frame on the heap.

+
+
+

You have now learned how promise types and coroutine handles work together to create useful abstractions like generators. In the next section, you will explore advanced topics: symmetric transfer, allocation, and exception handling.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/2.cpp20-coroutines/2d.advanced.html b/preview/2.cpp20-coroutines/2d.advanced.html new file mode 100644 index 0000000..3309abc --- /dev/null +++ b/preview/2.cpp20-coroutines/2d.advanced.html @@ -0,0 +1,999 @@ + + + + + + + + + + + + + + Part IV: Advanced Topics :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part IV: Advanced Topics

+
+
+
+

This section covers advanced coroutine topics: symmetric transfer for efficient resumption, coroutine allocation strategies, and exception handling. These concepts are essential for building production-quality coroutine types.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Symmetric Transfer

+
+
+

When a coroutine completes or awaits another coroutine, control must transfer somewhere. The naive approach—simply calling handle.resume()—has a problem: each nested coroutine adds a frame to the call stack. With deep nesting, you risk stack overflow.

+
+
+

Symmetric transfer solves this by returning a coroutine handle from await_suspend. Instead of resuming the target coroutine via a function call, the compiler generates a tail call that transfers control without growing the stack.

+
+
+

The Problem: Stack Accumulation

+
+

Consider a chain of coroutines where each awaits the next:

+
+
+
+
task<> a() { co_await b(); }
+task<> b() { co_await c(); }
+task<> c() { co_return; }
+
+
+
+

Without symmetric transfer, when a awaits b:

+
+
+
    +
  1. +

    a calls into the awaiter’s await_suspend

    +
  2. +
  3. +

    await_suspend calls b.handle.resume()

    +
  4. +
  5. +

    b runs, calls into its awaiter’s await_suspend

    +
  6. +
  7. +

    That calls c.handle.resume()

    +
  8. +
  9. +

    The stack now has frames for `a’s suspension, `b’s suspension, and `c’s execution

    +
  10. +
+
+
+

Each suspension adds a stack frame. With thousands of nested coroutines, the stack overflows.

+
+
+
+

The Solution: Return the Handle

+
+

await_suspend can return a std::coroutine_handle<>:

+
+
+
+
std::coroutine_handle<> await_suspend(std::coroutine_handle<> h)
+{
+    // store continuation for later
+    continuation_ = h;
+
+    // return handle to resume (instead of calling resume())
+    return next_coroutine_;
+}
+
+
+
+

When await_suspend returns a handle, the compiler generates code equivalent to:

+
+
+
+
auto next = awaiter.await_suspend(current);
+if (next != std::noop_coroutine())
+    next.resume();  // tail call, doesn't grow stack
+
+
+
+

The key insight: returning a handle enables the compiler to implement the resumption as a tail call. The current stack frame is reused for the next coroutine.

+
+
+
+

Return Types for await_suspend

+
+

await_suspend can return three types:

+
+
+
+
void
+
+

Always suspend. The coroutine is suspended and some external mechanism must resume it.

+
+
bool
+
+

Conditional suspension. Return true to suspend, false to continue without suspending.

+
+
std::coroutine_handle<>
+
+

Symmetric transfer. The returned handle is resumed; returning std::noop_coroutine() suspends without resuming anything.

+
+
+
+
+
+

Using Symmetric Transfer in Generators

+
+

A production generator uses symmetric transfer at final_suspend to return to whoever is iterating:

+
+
+
+
auto final_suspend() noexcept
+{
+    struct awaiter
+    {
+        promise_type* p_;
+
+        bool await_ready() const noexcept { return false; }
+
+        std::coroutine_handle<> await_suspend(std::coroutine_handle<>) noexcept
+        {
+            // Return to the consumer that called resume()
+            return p_->consumer_handle_;
+        }
+
+        void await_resume() const noexcept {}
+    };
+    return awaiter{this};
+}
+
+
+
+
+
+
+

Coroutine Allocation

+
+
+

Every coroutine needs memory for its coroutine frame—the heap-allocated structure holding local variables, parameters, and suspension state.

+
+
+

Default Allocation

+
+

By default, coroutines allocate their frames using operator new. The frame size depends on:

+
+
+
    +
  • +

    Local variables in the coroutine

    +
  • +
  • +

    Parameters (copied into the frame)

    +
  • +
  • +

    Promise type members

    +
  • +
  • +

    Compiler-generated bookkeeping

    +
  • +
+
+
+
+

Heap Allocation eLision Optimization (HALO)

+
+

Compilers can sometimes eliminate coroutine frame allocation entirely through HALO (Heap Allocation eLision Optimization). When the compiler can prove that:

+
+
+
    +
  • +

    The coroutine’s lifetime is contained within the caller’s lifetime

    +
  • +
  • +

    The frame size is known at compile time

    +
  • +
+
+
+

…​it may allocate the frame on the caller’s stack instead of the heap.

+
+
+

HALO is most effective when:

+
+
+
    +
  • +

    Coroutines are awaited immediately after creation

    +
  • +
  • +

    The coroutine type is marked with (Clang extension)

    +
  • +
  • +

    Optimization is enabled (-O2 or higher)

    +
  • +
+
+
+
+
// HALO might apply here because the task is awaited immediately
+co_await compute_something();
+
+// HALO cannot apply here because the task escapes
+auto task = compute_something();
+store_for_later(std::move(task));
+
+
+
+
+

Custom Allocators

+
+

Promise types can customize allocation by providing operator new and operator delete:

+
+
+
+
struct promise_type
+{
+    // Custom allocation
+    static void* operator new(std::size_t size)
+    {
+        return my_allocator.allocate(size);
+    }
+
+    static void operator delete(void* ptr, std::size_t size)
+    {
+        my_allocator.deallocate(ptr, size);
+    }
+
+    // ... rest of promise type
+};
+
+
+
+

The promise’s operator new receives only the frame size. To access allocator arguments passed to the coroutine, use the leading allocator convention with std::allocator_arg_t as the first parameter.

+
+
+
+
+
+

Exception Handling

+
+
+

Exceptions in coroutines require special handling because a coroutine can suspend and resume across different call stacks.

+
+
+

The Exception Flow

+
+

When an exception is thrown inside a coroutine and not caught:

+
+
+
    +
  1. +

    The exception is caught by an implicit try-catch surrounding the coroutine body

    +
  2. +
  3. +

    promise.unhandled_exception() is called while the exception is active

    +
  4. +
  5. +

    After unhandled_exception() returns, co_await promise.final_suspend() executes

    +
  6. +
  7. +

    The coroutine completes (suspended or destroyed, depending on final_suspend)

    +
  8. +
+
+
+
+

Options in unhandled_exception()

+
+

Terminate the program:

+
+
+
+
void unhandled_exception()
+{
+    std::terminate();
+}
+
+
+
+

Store for later retrieval:

+
+
+
+
void unhandled_exception()
+{
+    exception_ = std::current_exception();
+}
+
+
+
+

Rethrow immediately:

+
+
+
+
void unhandled_exception()
+{
+    throw;  // propagates to whoever resumed the coroutine
+}
+
+
+
+

Swallow the exception:

+
+
+
+
void unhandled_exception()
+{
+    // silently ignored - almost always a mistake
+}
+
+
+
+
+

The Store-and-Rethrow Pattern

+
+

For tasks and generators where callers expect results, store the exception and rethrow it when results are requested:

+
+
+
+
struct promise_type
+{
+    std::exception_ptr exception_;
+
+    void unhandled_exception()
+    {
+        exception_ = std::current_exception();
+    }
+};
+
+// In the return object's result accessor:
+T get_result()
+{
+    if (handle_.promise().exception_)
+        std::rethrow_exception(handle_.promise().exception_);
+    return std::move(handle_.promise().result_);
+}
+
+
+
+
+

Exception Example

+
+
+
#include <coroutine>
+#include <exception>
+#include <iostream>
+#include <stdexcept>
+
+struct Task
+{
+    struct promise_type
+    {
+        std::exception_ptr exception;
+
+        Task get_return_object()
+        {
+            return Task{std::coroutine_handle<promise_type>::from_promise(*this)};
+        }
+
+        std::suspend_always initial_suspend() { return {}; }
+        std::suspend_always final_suspend() noexcept { return {}; }
+        void return_void() {}
+
+        void unhandled_exception()
+        {
+            exception = std::current_exception();
+        }
+    };
+
+    std::coroutine_handle<promise_type> handle;
+
+    Task(std::coroutine_handle<promise_type> h) : handle(h) {}
+    ~Task() { if (handle) handle.destroy(); }
+
+    void run() { handle.resume(); }
+
+    void check_exception()
+    {
+        if (handle.promise().exception)
+            std::rethrow_exception(handle.promise().exception);
+    }
+};
+
+Task risky_operation()
+{
+    std::cout << "Starting risky operation" << std::endl;
+    throw std::runtime_error("Something went wrong");
+    co_return;  // never reached
+}
+
+int main()
+{
+    Task task = risky_operation();
+
+    try
+    {
+        task.run();
+        task.check_exception();
+        std::cout << "Operation completed successfully" << std::endl;
+    }
+    catch (std::exception const& e)
+    {
+        std::cout << "Operation failed: " << e.what() << std::endl;
+    }
+}
+
+
+
+

Output:

+
+
+
+
Starting risky operation
+Operation failed: Something went wrong
+
+
+
+
+

Initialization Exceptions

+
+

Exceptions thrown before the first suspension point (before initial_suspend completes) propagate directly to the caller without going through unhandled_exception(). If initial_suspend() returns suspend_always, the coroutine suspends before any user code runs, avoiding this edge case.

+
+
+
+
+
+

Building a Production Generator

+
+
+

With all these concepts, here is a production-quality generic generator:

+
+
+
+
#include <coroutine>
+#include <exception>
+#include <utility>
+
+template<typename T>
+class Generator
+{
+public:
+    struct promise_type
+    {
+        T value_;
+        std::exception_ptr exception_;
+
+        Generator get_return_object()
+        {
+            return Generator{Handle::from_promise(*this)};
+        }
+
+        std::suspend_always initial_suspend() noexcept { return {}; }
+        std::suspend_always final_suspend() noexcept { return {}; }
+
+        std::suspend_always yield_value(T v)
+        {
+            value_ = std::move(v);
+            return {};
+        }
+
+        void return_void() noexcept {}
+
+        void unhandled_exception()
+        {
+            exception_ = std::current_exception();
+        }
+
+        // Prevent co_await inside generators
+        template<typename U>
+        std::suspend_never await_transform(U&&) = delete;
+    };
+
+    using Handle = std::coroutine_handle<promise_type>;
+
+    class iterator
+    {
+        Handle handle_;
+
+    public:
+        using iterator_category = std::input_iterator_tag;
+        using value_type = T;
+        using difference_type = std::ptrdiff_t;
+
+        iterator() : handle_(nullptr) {}
+        explicit iterator(Handle h) : handle_(h) {}
+
+        iterator& operator++()
+        {
+            handle_.resume();
+            if (handle_.done())
+            {
+                auto& promise = handle_.promise();
+                handle_ = nullptr;
+                if (promise.exception_)
+                    std::rethrow_exception(promise.exception_);
+            }
+            return *this;
+        }
+
+        T& operator*() const { return handle_.promise().value_; }
+        bool operator==(iterator const& other) const
+        {
+            return handle_ == other.handle_;
+        }
+    };
+
+    iterator begin()
+    {
+        if (handle_)
+        {
+            handle_.resume();
+            if (handle_.done())
+            {
+                auto& promise = handle_.promise();
+                if (promise.exception_)
+                    std::rethrow_exception(promise.exception_);
+                return iterator{};
+            }
+        }
+        return iterator{handle_};
+    }
+
+    iterator end() { return iterator{}; }
+
+    ~Generator() { if (handle_) handle_.destroy(); }
+
+    Generator(Generator const&) = delete;
+    Generator& operator=(Generator const&) = delete;
+
+    Generator(Generator&& other) noexcept
+        : handle_(std::exchange(other.handle_, nullptr)) {}
+
+    Generator& operator=(Generator&& other) noexcept
+    {
+        if (this != &other)
+        {
+            if (handle_) handle_.destroy();
+            handle_ = std::exchange(other.handle_, nullptr);
+        }
+        return *this;
+    }
+
+private:
+    Handle handle_;
+
+    explicit Generator(Handle h) : handle_(h) {}
+};
+
+
+
+

This generator:

+
+
+
    +
  • +

    Provides a standard iterator interface for range-based for loops

    +
  • +
  • +

    Stores and rethrows exceptions during iteration

    +
  • +
  • +

    Prevents co_await inside generators via deleted await_transform

    +
  • +
  • +

    Manages coroutine lifetime with RAII

    +
  • +
  • +

    Supports move semantics

    +
  • +
+
+
+
+
+

Conclusion

+
+
+

You have now learned the complete mechanics of C++20 coroutines:

+
+
+
    +
  • +

    Keywordsco_await, co_yield, and co_return transform functions into coroutines

    +
  • +
  • +

    Promise types — Control coroutine behavior at initialization, suspension, completion, and error handling

    +
  • +
  • +

    Coroutine handles — Lightweight references for resuming, querying, and destroying coroutines

    +
  • +
  • +

    Symmetric transfer — Efficient control flow without stack accumulation

    +
  • +
  • +

    Allocation — Custom allocation and HALO optimization

    +
  • +
  • +

    Exception handling — Capturing and propagating exceptions across suspension points

    +
  • +
+
+
+

These fundamentals prepare you for understanding Capy’s task<T> type and the IoAwaitable protocol, which build on standard coroutine machinery with executor affinity and stop token propagation.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/3.concurrency/3.intro.html b/preview/3.concurrency/3.intro.html new file mode 100644 index 0000000..8eed669 --- /dev/null +++ b/preview/3.concurrency/3.intro.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + Introduction to Concurrency :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Introduction to Concurrency

+
+

Your processor has multiple cores. Your operating system runs hundreds of threads. Your users expect responsive interfaces while your server handles thousands of simultaneous connections. Concurrency is not an advanced topic reserved for specialists—​it is the reality of modern software.

+
+
+

Yet concurrent programming has a reputation for being treacherous, and that reputation is earned. Two threads reading and writing the same variable can produce results that are impossible to reproduce, impossible to debug, and impossible to reason about by staring at the code. A program that passes every test can still corrupt data in production under load. The bugs are real, and they are subtle.

+
+
+

The good news: these problems are well understood. Decades of research and practice have produced clear patterns, precise vocabulary, and reliable tools. Once you understand the fundamentals—​what a data race actually is, why memory ordering matters, how synchronization primitives work—​concurrent code becomes something you can reason about with confidence.

+
+
+

This section builds your understanding of concurrency from first principles. No prior experience with threads or parallel programming is needed. You will learn what makes concurrent code hard to reason about, how the standard synchronization tools work, and the architectural patterns that tame that complexity. When you finish, you will have the vocabulary and mental models to understand how Capy’s coroutine-based concurrency works under the hood—​and why it eliminates entire categories of the bugs described here.

+
+ + +
+
+ +
+ + diff --git a/preview/3.concurrency/3a.foundations.html b/preview/3.concurrency/3a.foundations.html new file mode 100644 index 0000000..0ef43e3 --- /dev/null +++ b/preview/3.concurrency/3a.foundations.html @@ -0,0 +1,678 @@ + + + + + + + + + + + + + + Part I: Foundations :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part I: Foundations

+
+
+
+

This section introduces the fundamental concepts of concurrent programming. You will learn what concurrency is, why it matters, and how threads provide the foundation for parallel execution.

+
+
+
+
+

Prerequisites

+
+
+

Before beginning this tutorial, you should have:

+
+
+
    +
  • +

    A C++ compiler with C++11 or later support

    +
  • +
  • +

    Familiarity with basic C++ concepts: functions, classes, and lambdas

    +
  • +
  • +

    Understanding of how programs execute sequentially

    +
  • +
+
+
+
+
+

Why Concurrency Matters

+
+
+

Modern computers have multiple processor cores. A quad-core laptop can do four things at once. But most programs use only one core, leaving the others idle. Concurrency lets you use all your processing power.

+
+
+

Consider downloading a large file. Without concurrency, your application freezes—the user interface becomes unresponsive because your single thread of execution is busy waiting for network data. With concurrency, one thread handles the download while another keeps the interface responsive. The user can continue working, cancel the download, or start another—all while data streams in.

+
+
+

The benefits compound in computationally intensive work. Image processing, scientific simulations, video encoding—these tasks can be split into independent pieces. Process them simultaneously and your program finishes in a fraction of the time.

+
+
+

But concurrency is not free. It introduces complexity. Multiple threads accessing the same data can corrupt it. Threads waiting on each other can freeze forever. These problems—race conditions and deadlocks—are the challenges you will learn to handle.

+
+
+
+
+

Threads—Your Program’s Parallel Lives

+
+
+

When you run a program, the operating system creates a process for it. This process gets its own memory space, its own resources, and at least one thread of execution—the main thread.

+
+
+

Think of a thread as a bookmark in a book of instructions. It marks where you are in the code. The processor reads the instruction at that bookmark, executes it, and moves the bookmark forward. One thread means one bookmark—your program can only be at one place in the code at a time.

+
+
+

But you can create additional threads. Each thread is its own bookmark, tracking its own position in the code. Now your program can be at multiple places simultaneously. Each thread has its own call stack—its own record of which functions called which—but all threads share the same heap memory.

+
+
+

This sharing is both the power and the peril of threads.

+
+
+
+
+

Creating Threads

+
+
+

The <thread> header provides std::thread, the standard way to create threads in C++.

+
+
+
+
#include <iostream>
+#include <thread>
+
+void say_hello()
+{
+    std::cout << "Hello from a new thread!\n";
+}
+
+int main()
+{
+    std::thread t(say_hello);
+    t.join();
+    std::cout << "Back in the main thread.\n";
+    return 0;
+}
+
+
+
+

The std::thread constructor takes a function (or any callable) and immediately starts a new thread running that function. Two bookmarks now move through your code simultaneously.

+
+
+

The join() call makes the main thread wait until thread t finishes. Without it, main() might return and terminate the program before say_hello() completes. Always join your threads before they go out of scope.

+
+
+

Parallel Execution

+
+
+
#include <iostream>
+#include <thread>
+
+void count_up(char const* name)
+{
+    for (int i = 1; i <= 5; ++i)
+        std::cout << name << ": " << i << "\n";
+}
+
+int main()
+{
+    std::thread alice(count_up, "Alice");
+    std::thread bob(count_up, "Bob");
+
+    alice.join();
+    bob.join();
+
+    return 0;
+}
+
+
+
+

Run this and you might see output like:

+
+
+
+
Alice: 1
+Bob: 1
+Alice: 2
+Bob: 2
+Alice: 3
+...
+
+
+
+

Or perhaps:

+
+
+
+
AliceBob: : 1
+1
+Alice: 2
+...
+
+
+
+

The interleaving varies each run. Both threads race to print, and their outputs jumble together. This unpredictability is your first glimpse of concurrent programming’s fundamental challenge: when threads share resources (here, std::cout), chaos can ensue.

+
+
+
+
+
+

Ways to Create Threads

+
+
+

Threads accept any callable object: functions, lambda expressions, function objects (functors), and member functions.

+
+
+

Lambda Expressions

+
+

Lambda expressions are often the clearest choice:

+
+
+
+
#include <iostream>
+#include <thread>
+
+int main()
+{
+    int x = 42;
+
+    std::thread t([x]() {
+        std::cout << "The value is: " << x << "\n";
+    });
+
+    t.join();
+    return 0;
+}
+
+
+
+

The lambda captures x by value—it copies x into the lambda. By default, std::thread copies all arguments passed to it. Even if your function declares a reference parameter, the thread receives a copy.

+
+
+

To pass by reference, use std::ref():

+
+
+
+
#include <iostream>
+#include <thread>
+
+void increment(int& value)
+{
+    ++value;
+}
+
+int main()
+{
+    int counter = 0;
+
+    std::thread t(increment, std::ref(counter));
+    t.join();
+
+    std::cout << "Counter is now: " << counter << "\n";
+    return 0;
+}
+
+
+
+

Without std::ref(), the thread would modify a copy, leaving counter unchanged.

+
+
+
+

Member Functions

+
+

For member functions, pass a pointer to the function and an instance:

+
+
+
+
#include <iostream>
+#include <thread>
+#include <string>
+
+class Greeter
+{
+public:
+    void greet(std::string const& name)
+    {
+        std::cout << "Hello, " << name << "!\n";
+    }
+};
+
+int main()
+{
+    Greeter g;
+    std::thread t(&Greeter::greet, &g, "World");
+    t.join();
+    return 0;
+}
+
+
+
+

The &Greeter::greet syntax names the member function; &g provides the instance to call it on.

+
+
+
+
+
+

Thread Lifecycle: Join, Detach, and Destruction

+
+
+

Every thread must be either joined or detached before its std::thread object is destroyed. Failing to do so calls std::terminate(), abruptly ending your program.

+
+
+

join()

+
+

join() blocks the calling thread until the target thread finishes. This is how you wait for work to complete:

+
+
+
+
std::thread t(do_work);
+// ... do other things ...
+t.join();  // wait for do_work to finish
+
+
+
+
+

detach()

+
+

Sometimes you want a thread to run independently, continuing even after the std::thread object is destroyed. That is what detach() does:

+
+
+
+
std::thread t(background_task);
+t.detach();  // thread runs independently
+// t is now "empty"—no longer associated with a thread
+
+
+
+

A detached thread becomes a daemon thread. It runs until it finishes or the program exits. You lose all ability to wait for it or check its status. Use detachment sparingly—usually for fire-and-forget background work.

+
+
+
+

Checking joinable()

+
+

Before joining or detaching, you can check if a thread is joinable:

+
+
+
+
std::thread t(some_function);
+
+if (t.joinable())
+{
+    t.join();
+}
+
+
+
+

A thread is joinable if it represents an actual thread of execution. After joining or detaching, or after default construction, a std::thread is not joinable.

+
+
+

You have now learned the basics of threads: creation, execution, and lifecycle management. In the next section, you will learn about the dangers of shared data and how to protect it with synchronization primitives.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/3.concurrency/3b.synchronization.html b/preview/3.concurrency/3b.synchronization.html new file mode 100644 index 0000000..6e7a30e --- /dev/null +++ b/preview/3.concurrency/3b.synchronization.html @@ -0,0 +1,650 @@ + + + + + + + + + + + + + + Part II: Synchronization :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part II: Synchronization

+
+
+
+

This section introduces the dangers of shared data access and the synchronization primitives that protect against them. You will learn about race conditions, mutexes, lock guards, and deadlocks.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

The Danger: Race Conditions

+
+
+

When multiple threads read the same data, all is well. But when at least one thread writes while others read or write, you have a data race. The result is undefined behavior—crashes, corruption, or silent errors.

+
+
+

Consider this code:

+
+
+
+
#include <iostream>
+#include <thread>
+
+int counter = 0;
+
+void increment_many_times()
+{
+    for (int i = 0; i < 100000; ++i)
+        ++counter;
+}
+
+int main()
+{
+    std::thread t1(increment_many_times);
+    std::thread t2(increment_many_times);
+
+    t1.join();
+    t2.join();
+
+    std::cout << "Counter: " << counter << "\n";
+    return 0;
+}
+
+
+
+

Two threads, each incrementing 100,000 times. You would expect 200,000. But run this repeatedly and you will see different results—180,000, 195,327, maybe occasionally 200,000. Something is wrong.

+
+
+

The ++counter operation looks atomic—indivisible—but it is not. It actually consists of three steps:

+
+
+
    +
  1. +

    Read the current value

    +
  2. +
  3. +

    Add one

    +
  4. +
  5. +

    Write the result back

    +
  6. +
+
+
+

Between any of these steps, the other thread might execute its own steps. Imagine both threads read counter when it is 5. Both add one, getting 6. Both write 6 back. Two increments, but the counter only went up by one. This is a lost update, a classic race condition.

+
+
+

The more threads, the more opportunity for races. The faster your processor, the more instructions execute between context switches, potentially hiding the bug—until one critical day in production.

+
+
+
+
+

Mutual Exclusion: Mutexes

+
+
+

The solution to data races is mutual exclusion: ensuring that only one thread accesses shared data at a time.

+
+
+

A mutex (mutual exclusion object) is a lockable resource. Before accessing shared data, a thread locks the mutex. If another thread already holds the lock, the requesting thread blocks until the lock is released. This serializes access to the protected data.

+
+
+
+
#include <iostream>
+#include <thread>
+#include <mutex>
+
+int counter = 0;
+std::mutex counter_mutex;
+
+void increment_many_times()
+{
+    for (int i = 0; i < 100000; ++i)
+    {
+        counter_mutex.lock();
+        ++counter;
+        counter_mutex.unlock();
+    }
+}
+
+int main()
+{
+    std::thread t1(increment_many_times);
+    std::thread t2(increment_many_times);
+
+    t1.join();
+    t2.join();
+
+    std::cout << "Counter: " << counter << "\n";
+    return 0;
+}
+
+
+
+

Now the output is always 200,000. The mutex ensures that between lock() and unlock(), only one thread executes. The increment is now effectively atomic.

+
+
+

But there is a problem with calling lock() and unlock() directly. If code between them throws an exception, unlock() never executes. The mutex stays locked forever, and any thread waiting for it blocks eternally—a deadlock.

+
+
+
+
+

Lock Guards: Safety Through RAII

+
+
+

C++ has a powerful idiom: RAII (Resource Acquisition Is Initialization). The idea: acquire resources in a constructor, release them in the destructor. Since destructors run even when exceptions are thrown, cleanup is guaranteed.

+
+
+

Lock guards apply RAII to mutexes:

+
+
+
+
#include <iostream>
+#include <thread>
+#include <mutex>
+
+int counter = 0;
+std::mutex counter_mutex;
+
+void increment_many_times()
+{
+    for (int i = 0; i < 100000; ++i)
+    {
+        std::lock_guard<std::mutex> lock(counter_mutex);
+        ++counter;
+        // lock is automatically released when it goes out of scope
+    }
+}
+
+
+
+

The std::lock_guard locks the mutex on construction and unlocks it on destruction. Even if an exception is thrown, the destructor runs and the mutex is released. This is the correct way to use mutexes.

+
+
+

std::scoped_lock (C++17)

+
+

Since C++17, std::scoped_lock is preferred. It works like lock_guard but can lock multiple mutexes simultaneously, avoiding a class of deadlock:

+
+
+
+
std::scoped_lock lock(counter_mutex);  // C++17
+
+
+
+
+

std::unique_lock

+
+

For more control, use std::unique_lock. It can be unlocked before destruction, moved to another scope, or created without immediately locking:

+
+
+
+
std::unique_lock<std::mutex> lock(some_mutex, std::defer_lock);
+// mutex not yet locked
+
+lock.lock();  // lock when ready
+// ... do work ...
+lock.unlock();  // unlock early if needed
+// ... do other work ...
+// destructor unlocks again if still locked
+
+
+
+

std::unique_lock is more flexible but slightly more expensive than std::lock_guard. Use the simplest tool that does the job.

+
+
+
+
+
+

The Deadlock Dragon

+
+
+

Mutexes solve data races but introduce a new danger: deadlock.

+
+
+

Imagine two threads and two mutexes. Thread A locks mutex 1, then tries to lock mutex 2. Thread B locks mutex 2, then tries to lock mutex 1. Each thread holds one mutex and waits for the other. Neither can proceed. The program freezes.

+
+
+
+
std::mutex mutex1, mutex2;
+
+void thread_a()
+{
+    std::lock_guard<std::mutex> lock1(mutex1);
+    std::lock_guard<std::mutex> lock2(mutex2);  // blocks, waiting for B
+    // ...
+}
+
+void thread_b()
+{
+    std::lock_guard<std::mutex> lock2(mutex2);
+    std::lock_guard<std::mutex> lock1(mutex1);  // blocks, waiting for A
+    // ...
+}
+
+
+
+

If both threads run and each acquires its first mutex before the other acquires the second, deadlock occurs.

+
+
+

Preventing Deadlock

+
+

The simplest prevention: always lock mutexes in the same order. If every thread locks mutex1 before mutex2, no cycle can form.

+
+
+

When you need to lock multiple mutexes and cannot guarantee order, use std::scoped_lock:

+
+
+
+
void safe_function()
+{
+    std::scoped_lock lock(mutex1, mutex2);  // locks both atomically
+    // ...
+}
+
+
+
+

std::scoped_lock uses a deadlock-avoidance algorithm internally, acquiring both mutexes without risk of circular waiting.

+
+
+
+

Deadlock Prevention Rules

+
+
    +
  1. +

    Lock in consistent order — Define a global ordering for mutexes and always lock in that order

    +
  2. +
  3. +

    Use std::scoped_lock for multiple mutexes — Let the library handle deadlock avoidance

    +
  4. +
  5. +

    Hold locks for minimal time — Reduce the window for contention

    +
  6. +
  7. +

    Avoid nested locks when possible — Simpler designs prevent deadlock by construction

    +
  8. +
+
+
+

You have now learned about race conditions, mutexes, lock guards, and deadlocks. In the next section, you will explore advanced synchronization primitives: atomics, condition variables, and shared locks.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/3.concurrency/3c.advanced.html b/preview/3.concurrency/3c.advanced.html new file mode 100644 index 0000000..2dde6ee --- /dev/null +++ b/preview/3.concurrency/3c.advanced.html @@ -0,0 +1,697 @@ + + + + + + + + + + + + + + Part III: Advanced Primitives :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part III: Advanced Primitives

+
+
+
+

This section covers advanced synchronization primitives: atomics for lock-free operations, condition variables for efficient waiting, and shared locks for reader/writer patterns.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Atomics: Lock-Free Operations

+
+
+

For operations on individual values, mutexes might be overkill. Atomic types provide lock-free thread safety for single variables.

+
+
+

An atomic operation completes entirely before any other thread can observe its effects. There is no intermediate state.

+
+
+
+
#include <iostream>
+#include <thread>
+#include <atomic>
+
+std::atomic<int> counter{0};
+
+void increment_many_times()
+{
+    for (int i = 0; i < 100000; ++i)
+        ++counter;  // atomic increment
+}
+
+int main()
+{
+    std::thread t1(increment_many_times);
+    std::thread t2(increment_many_times);
+
+    t1.join();
+    t2.join();
+
+    std::cout << "Counter: " << counter << "\n";
+    return 0;
+}
+
+
+
+

No mutex, no lock guard, yet the result is always 200,000. The std::atomic<int> ensures that increments are indivisible.

+
+
+

When to Use Atomics

+
+

Atomics work best for single-variable operations: counters, flags, simple state. They are faster than mutexes when contention is low. But they cannot protect complex operations involving multiple variables—for that, you need mutexes.

+
+
+

Common atomic types include:

+
+
+
    +
  • +

    std::atomic<bool> — Thread-safe boolean flag

    +
  • +
  • +

    std::atomic<int> — Thread-safe integer counter

    +
  • +
  • +

    std::atomic<T*> — Thread-safe pointer

    +
  • +
  • +

    std::atomic<std::shared_ptr<T>> — Thread-safe shared pointer (C++20)

    +
  • +
+
+
+

Any trivially copyable type can be made atomic.

+
+
+
+

Atomic Operations

+
+
+
std::atomic<int> value{0};
+
+value.store(42);              // atomic write
+int x = value.load();         // atomic read
+int old = value.exchange(10); // atomic read-modify-write
+value.fetch_add(5);           // atomic addition, returns old value
+value.fetch_sub(3);           // atomic subtraction, returns old value
+
+// Compare-and-swap (CAS)
+int expected = 10;
+bool success = value.compare_exchange_strong(expected, 20);
+// If value == expected, sets value = 20 and returns true
+// Otherwise, sets expected = value and returns false
+
+
+
+
+
+
+

Condition Variables: Efficient Waiting

+
+
+

Sometimes a thread must wait for a specific condition before proceeding. You could loop, repeatedly checking:

+
+
+
+
// Inefficient busy-wait
+while (!ready)
+{
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+}
+
+
+
+

This works but wastes CPU cycles and introduces latency. Condition variables provide efficient waiting.

+
+
+

A condition variable allows one thread to signal others that something has changed. Waiting threads sleep until notified, consuming no CPU.

+
+
+
+
#include <iostream>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+
+std::mutex mtx;
+std::condition_variable cv;
+bool ready = false;
+
+void worker()
+{
+    std::unique_lock<std::mutex> lock(mtx);
+    cv.wait(lock, []{ return ready; });  // wait until ready is true
+    std::cout << "Worker proceeding!\n";
+}
+
+void signal_ready()
+{
+    {
+        std::lock_guard<std::mutex> lock(mtx);
+        ready = true;
+    }
+    cv.notify_one();  // wake one waiting thread
+}
+
+int main()
+{
+    std::thread t(worker);
+
+    std::this_thread::sleep_for(std::chrono::seconds(1));
+    signal_ready();
+
+    t.join();
+    return 0;
+}
+
+
+
+

The worker thread calls cv.wait(), which atomically releases the mutex and suspends the thread. When signal_ready() calls notify_one(), the worker wakes up, reacquires the mutex, checks the condition, and proceeds.

+
+
+

The Predicate

+
+

The lambda []{ return ready; } is the predicate. wait() will not return until this evaluates to true. This guards against spurious wakeups—rare events where a thread wakes without notification. Always use a predicate.

+
+
+
+

Notification Methods

+
+
    +
  • +

    notify_one() — Wake a single waiting thread

    +
  • +
  • +

    notify_all() — Wake all waiting threads

    +
  • +
+
+
+

Use notify_one() when only one thread needs to proceed (e.g., producer-consumer with single consumer). Use notify_all() when multiple threads might need to check the condition (e.g., broadcast events, shutdown signals).

+
+
+
+

Wait Variants

+
+
+
// Wait indefinitely
+cv.wait(lock, predicate);
+
+// Wait with timeout
+auto status = cv.wait_for(lock, std::chrono::seconds(5), predicate);
+// Returns true if predicate is true, false on timeout
+
+// Wait until specific time point
+auto status = cv.wait_until(lock, deadline, predicate);
+
+
+
+
+
+
+

Shared Locks: Readers and Writers

+
+
+

Consider a data structure that is read frequently but written rarely. A regular mutex serializes all access—but why block readers from each other? Multiple threads can safely read simultaneously; only writes require exclusive access.

+
+
+

Shared mutexes support this pattern:

+
+
+
+
#include <iostream>
+#include <thread>
+#include <shared_mutex>
+#include <vector>
+
+std::shared_mutex rw_mutex;
+std::vector<int> data;
+
+void reader(int id)
+{
+    std::shared_lock<std::shared_mutex> lock(rw_mutex);  // shared access
+    std::cout << "Reader " << id << " sees " << data.size() << " elements\n";
+}
+
+void writer(int value)
+{
+    std::unique_lock<std::shared_mutex> lock(rw_mutex);  // exclusive access
+    data.push_back(value);
+    std::cout << "Writer added " << value << "\n";
+}
+
+
+
+

Lock Types

+
+
+
std::shared_lock
+
+

Acquires a shared lock—multiple threads can hold shared locks simultaneously.

+
+
std::unique_lock (on shared_mutex)
+
+

Acquires an exclusive lock—no other locks (shared or exclusive) can be held.

+
+
+
+
+
+

Behavior

+
+
    +
  • +

    While any reader holds a shared lock, writers must wait

    +
  • +
  • +

    While a writer holds an exclusive lock, everyone waits

    +
  • +
  • +

    Multiple readers can proceed simultaneously

    +
  • +
+
+
+

This pattern maximizes concurrency for read-heavy workloads. Use std::shared_mutex when reads vastly outnumber writes.

+
+
+
+

Example: Thread-Safe Cache

+
+
+
#include <shared_mutex>
+#include <unordered_map>
+#include <string>
+#include <optional>
+
+class ThreadSafeCache
+{
+    std::unordered_map<std::string, std::string> cache_;
+    mutable std::shared_mutex mutex_;
+
+public:
+    std::optional<std::string> get(std::string const& key) const
+    {
+        std::shared_lock lock(mutex_);  // readers can proceed in parallel
+        auto it = cache_.find(key);
+        if (it != cache_.end())
+            return it->second;
+        return std::nullopt;
+    }
+
+    void put(std::string const& key, std::string const& value)
+    {
+        std::unique_lock lock(mutex_);  // exclusive access for writing
+        cache_[key] = value;
+    }
+};
+
+
+
+

Multiple threads can call get() simultaneously without blocking each other. Only put() requires exclusive access.

+
+
+

You have now learned about atomics, condition variables, and shared locks. In the next section, you will explore communication patterns: futures, promises, async, and practical concurrent patterns.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/3.concurrency/3d.patterns.html b/preview/3.concurrency/3d.patterns.html new file mode 100644 index 0000000..bce9626 --- /dev/null +++ b/preview/3.concurrency/3d.patterns.html @@ -0,0 +1,766 @@ + + + + + + + + + + + + + + Part IV: Communication & Patterns :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Part IV: Communication & Patterns

+
+
+
+

This section covers communication mechanisms for getting results from threads and practical patterns for concurrent programming.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Futures and Promises: Getting Results Back

+
+
+

Threads can perform work, but how do you get results from them? Passing references works but is clunky. C++ offers a cleaner abstraction: futures and promises.

+
+
+

A std::promise is a write-once container: a thread can set its value. A std::future is the corresponding read-once container: another thread can get that value. They form a one-way communication channel.

+
+
+
+
#include <iostream>
+#include <thread>
+#include <future>
+
+void compute(std::promise<int> result_promise)
+{
+    int answer = 6 * 7;  // expensive computation
+    result_promise.set_value(answer);
+}
+
+int main()
+{
+    std::promise<int> promise;
+    std::future<int> future = promise.get_future();
+
+    std::thread t(compute, std::move(promise));
+
+    std::cout << "Waiting for result...\n";
+    int result = future.get();  // blocks until value is set
+    std::cout << "The answer is: " << result << "\n";
+
+    t.join();
+    return 0;
+}
+
+
+
+

The worker thread calls set_value(). The main thread calls get(), which blocks until the value is available.

+
+
+

Important Behaviors

+
+
    +
  • +

    A future’s get() can only be called once

    +
  • +
  • +

    For multiple consumers, use std::shared_future

    +
  • +
  • +

    If the promise is destroyed without setting a value, get() throws std::future_error

    +
  • +
  • +

    set_exception() allows the worker to signal an error

    +
  • +
+
+
+
+
+
+

std::async: The Easy Path

+
+
+

Creating threads manually, managing promises, joining at the end—it is mechanical. std::async automates it:

+
+
+
+
#include <iostream>
+#include <future>
+
+int compute()
+{
+    return 6 * 7;
+}
+
+int main()
+{
+    std::future<int> future = std::async(compute);
+
+    std::cout << "Computing...\n";
+    int result = future.get();
+    std::cout << "Result: " << result << "\n";
+
+    return 0;
+}
+
+
+
+

std::async launches the function (potentially in a new thread), returning a future. No explicit thread creation, no promise management, no join call.

+
+
+

Launch Policies

+
+

By default, the system decides whether to run the function in a new thread or defer it until you call get(). You can specify:

+
+
+
+
// Force a new thread
+auto future = std::async(std::launch::async, compute);
+
+// Defer execution until get()
+auto future = std::async(std::launch::deferred, compute);
+
+// Let the system decide (default)
+auto future = std::async(std::launch::async | std::launch::deferred, compute);
+
+
+
+

For quick parallel tasks, std::async is often the cleanest choice.

+
+
+
+
+
+

Thread-Local Storage

+
+
+

Sometimes each thread needs its own copy of a variable—not shared, not copied each call, but persistent within that thread.

+
+
+

Declare it thread_local:

+
+
+
+
#include <iostream>
+#include <thread>
+
+thread_local int counter = 0;
+
+void increment_and_print(char const* name)
+{
+    ++counter;
+    std::cout << name << " counter: " << counter << "\n";
+}
+
+int main()
+{
+    std::thread t1([]{
+        increment_and_print("T1");
+        increment_and_print("T1");
+    });
+
+    std::thread t2([]{
+        increment_and_print("T2");
+        increment_and_print("T2");
+    });
+
+    t1.join();
+    t2.join();
+
+    return 0;
+}
+
+
+
+

Each thread sees its own counter. T1 prints 1, then 2. T2 independently prints 1, then 2. No synchronization needed because the data is not shared.

+
+
+

Thread-local storage is useful for per-thread caches, random number generators, or error state.

+
+
+
+
+

Practical Patterns

+
+
+

Producer-Consumer Queue

+
+

One or more threads produce work items; one or more threads consume them. A queue connects them:

+
+
+
+
#include <iostream>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <queue>
+
+template<typename T>
+class ThreadSafeQueue
+{
+    std::queue<T> queue_;
+    std::mutex mutex_;
+    std::condition_variable cv_;
+
+public:
+    void push(T value)
+    {
+        {
+            std::lock_guard<std::mutex> lock(mutex_);
+            queue_.push(std::move(value));
+        }
+        cv_.notify_one();
+    }
+
+    T pop()
+    {
+        std::unique_lock<std::mutex> lock(mutex_);
+        cv_.wait(lock, [this]{ return !queue_.empty(); });
+        T value = std::move(queue_.front());
+        queue_.pop();
+        return value;
+    }
+};
+
+
+
+

The producer pushes items; the consumer waits for items and processes them. The condition variable ensures the consumer sleeps efficiently when the queue is empty.

+
+
+
+
ThreadSafeQueue<int> work_queue;
+
+void producer()
+{
+    for (int i = 0; i < 10; ++i)
+    {
+        work_queue.push(i);
+        std::cout << "Produced: " << i << "\n";
+    }
+}
+
+void consumer()
+{
+    for (int i = 0; i < 10; ++i)
+    {
+        int item = work_queue.pop();
+        std::cout << "Consumed: " << item << "\n";
+    }
+}
+
+int main()
+{
+    std::thread prod(producer);
+    std::thread cons(consumer);
+
+    prod.join();
+    cons.join();
+
+    return 0;
+}
+
+
+
+
+

Parallel For

+
+

Split a loop across multiple threads:

+
+
+
+
#include <iostream>
+#include <thread>
+#include <vector>
+#include <functional>
+
+void parallel_for(int start, int end, int num_threads,
+                  std::function<void(int)> func)
+{
+    std::vector<std::thread> threads;
+    int chunk_size = (end - start) / num_threads;
+
+    for (int t = 0; t < num_threads; ++t)
+    {
+        int chunk_start = start + t * chunk_size;
+        int chunk_end = (t == num_threads - 1) ? end : chunk_start + chunk_size;
+
+        threads.emplace_back([=]{
+            for (int i = chunk_start; i < chunk_end; ++i)
+                func(i);
+        });
+    }
+
+    for (auto& thread : threads)
+        thread.join();
+}
+
+int main()
+{
+    std::mutex print_mutex;
+
+    parallel_for(0, 20, 4, [&](int i){
+        std::lock_guard<std::mutex> lock(print_mutex);
+        std::cout << "Processing " << i << " on thread "
+                  << std::this_thread::get_id() << "\n";
+    });
+
+    return 0;
+}
+
+
+
+

The work is divided into chunks, each handled by its own thread. For CPU-bound work on large datasets, this can dramatically reduce execution time.

+
+
+
+
+
+

Summary

+
+
+

You have learned the fundamentals of concurrent programming:

+
+
+
    +
  • +

    Threads — Independent flows of execution within a process

    +
  • +
  • +

    Mutexes — Mutual exclusion to prevent data races

    +
  • +
  • +

    Lock guards — RAII wrappers that ensure mutexes are properly released

    +
  • +
  • +

    Atomics — Lock-free safety for single operations

    +
  • +
  • +

    Condition variables — Efficient waiting for events

    +
  • +
  • +

    Shared locks — Multiple readers or one writer

    +
  • +
  • +

    Futures and promises — Communication of results between threads

    +
  • +
  • +

    std::async — Simplified launching of parallel work

    +
  • +
+
+
+

You have seen the dangers—race conditions, deadlocks—and the tools to avoid them.

+
+
+

Best Practices

+
+
    +
  • +

    Start with std::async when possible

    +
  • +
  • +

    Prefer immutable data — shared data that never changes needs no synchronization

    +
  • +
  • +

    Protect mutable shared state carefully — minimize the data that is shared

    +
  • +
  • +

    Minimize lock duration — hold locks for as brief a time as possible

    +
  • +
  • +

    Avoid nested locks — when unavoidable, use std::scoped_lock

    +
  • +
  • +

    Test thoroughly — test with many threads, on different machines, under load

    +
  • +
+
+
+

Concurrency is challenging. Bugs hide until the worst moment. Testing is hard because timing varies. But the rewards are substantial: responsive applications, full hardware utilization, and elegant solutions to naturally parallel problems.

+
+
+

This foundation prepares you for understanding Capy’s concurrency facilities: thread_pool, strand, when_all, and async_event. These build on standard primitives to provide coroutine-friendly concurrent programming.

+
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4.intro.html b/preview/4.coroutines/4.intro.html new file mode 100644 index 0000000..ab7b65e --- /dev/null +++ b/preview/4.coroutines/4.intro.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + Coroutines in Capy :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Coroutines in Capy

+
+

You know how C++20 coroutines work at the language level. You understand threads, synchronization, and the problems that concurrency introduces. Now it is time to see how Capy brings these together into a practical, high-performance library.

+
+
+

Capy’s coroutine model is built around a single principle: asynchronous code should look like synchronous code. You write a function that reads from a socket, processes the data, and writes a response—​top to bottom, with local variables and normal control flow. Capy handles suspension, resumption, thread scheduling, and cancellation behind the scenes. The result is code that is both easier to read and harder to get wrong.

+
+
+

But this is not magic, and it is not a black box. Every piece of Capy’s coroutine infrastructure is designed to be transparent. You can see how tasks are scheduled, control where they run, propagate cancellation, compose concurrent operations, and tune memory allocation. Understanding these mechanisms is what separates someone who uses the library from someone who uses it well.

+
+
+

This section is the bridge between theory and practice. You will see how Capy turns C++20 coroutines into a complete async programming model—​from launching and scheduling tasks, through cancellation and concurrent composition, to fine-grained control over memory allocation. Each topic builds on the last, and by the end you will be writing real asynchronous programs with Capy.

+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4a.tasks.html b/preview/4.coroutines/4a.tasks.html new file mode 100644 index 0000000..d11d990 --- /dev/null +++ b/preview/4.coroutines/4a.tasks.html @@ -0,0 +1,687 @@ + + + + + + + + + + + + + + The task Type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

The task Type

+
+
+
+

This section introduces Capy’s task<T> type—the fundamental coroutine type for asynchronous programming in Capy.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Overview

+
+
+

task<T> is Capy’s primary coroutine return type. It represents an asynchronous operation that eventually produces a value of type T (or nothing, for task<void>).

+
+
+

Key characteristics:

+
+
+
    +
  • +

    Lazy execution — The coroutine does not start until awaited

    +
  • +
  • +

    Symmetric transfer — Efficient resumption without stack accumulation

    +
  • +
  • +

    Executor inheritance — Inherits the caller’s executor unless explicitly bound

    +
  • +
  • +

    Stop token propagation — Forward-propagates cancellation signals

    +
  • +
  • +

    HALO support — Enables heap allocation elision when possible

    +
  • +
+
+
+
+
+

Declaring task Coroutines

+
+
+

Any function that returns task<T> and contains coroutine keywords (co_await, co_return) is a task coroutine:

+
+
+
+
#include <boost/capy.hpp>
+using namespace boost::capy;
+
+task<int> compute_value()
+{
+    co_return 42;
+}
+
+task<std::string> fetch_greeting()
+{
+    co_return "Hello, Capy!";
+}
+
+task<> do_nothing()  // task<void>
+{
+    co_return;
+}
+
+
+
+

The syntax task<> is equivalent to task<void> and represents a coroutine that completes without producing a value.

+
+
+
+
+

Returning Values with co_return

+
+
+

Use co_return to complete the coroutine and provide its result:

+
+
+
+
task<int> add(int a, int b)
+{
+    int result = a + b;
+    co_return result;  // Completes with value
+}
+
+task<> log_message(std::string msg)
+{
+    std::cout << msg << "\n";
+    co_return;  // Completes without value
+}
+
+
+
+

For task<void>, you can either use co_return; explicitly or let execution fall off the end of the function body.

+
+
+
+
+

Awaiting Other Tasks

+
+
+

Tasks can await other tasks using co_await. This is the primary mechanism for composing asynchronous operations:

+
+
+
+
task<int> step_one()
+{
+    co_return 10;
+}
+
+task<int> step_two(int x)
+{
+    co_return x * 2;
+}
+
+task<int> full_operation()
+{
+    int a = co_await step_one();  // Suspends until step_one completes
+    int b = co_await step_two(a); // Suspends until step_two completes
+    co_return b + 5;              // Final result: 25
+}
+
+
+
+

When you co_await a task:

+
+
+
    +
  1. +

    The current coroutine suspends

    +
  2. +
  3. +

    The awaited task starts executing

    +
  4. +
  5. +

    When the awaited task completes, the current coroutine resumes

    +
  6. +
  7. +

    The co_await expression evaluates to the awaited task’s result

    +
  8. +
+
+
+
+
+

Lazy Execution

+
+
+

A critical property of task<T> is lazy execution: creating a task does not start its execution. The coroutine body runs only when the task is awaited.

+
+
+
+
task<int> compute()
+{
+    std::cout << "Computing...\n";  // Not printed until awaited
+    co_return 42;
+}
+
+task<> example()
+{
+    auto t = compute();   // Task created, but "Computing..." NOT printed yet
+    std::cout << "Task created\n";
+
+    int result = co_await t;  // NOW "Computing..." is printed
+    std::cout << "Result: " << result << "\n";
+}
+
+
+
+

Output:

+
+
+
+
Task created
+Computing...
+Result: 42
+
+
+
+

Lazy execution enables efficient composition—tasks that are never awaited never run, consuming no resources beyond their initial allocation.

+
+
+
+
+

Symmetric Transfer

+
+
+

When a task completes, control transfers directly to its continuation (the coroutine that awaited it) using symmetric transfer. This avoids stack accumulation even with deep chains of coroutine calls.

+
+
+

Consider:

+
+
+
+
task<> a() { co_await b(); }
+task<> b() { co_await c(); }
+task<> c() { co_return; }
+
+
+
+

Without symmetric transfer, each co_await would add a stack frame, potentially causing stack overflow with deep nesting. With symmetric transfer, c returning to b returning to a uses constant stack space regardless of depth.

+
+
+

This is implemented through the await_suspend returning a coroutine handle rather than void:

+
+
+
+
// Inside task's final_suspend awaiter
+std::coroutine_handle<> await_suspend(std::coroutine_handle<>) const noexcept
+{
+    return continuation_;  // Transfer directly to continuation
+}
+
+
+
+
+
+

Move Semantics

+
+
+

Tasks are move-only. Copying a task would create aliasing problems where multiple handles reference the same coroutine frame.

+
+
+
+
task<int> compute();
+
+task<> example()
+{
+    auto t1 = compute();
+    auto t2 = std::move(t1);  // OK: ownership transferred
+
+    // auto t3 = t2;  // Error: task is not copyable
+
+    int result = co_await t2;  // t1 is now empty
+}
+
+
+
+

After moving, the source task becomes empty and must not be awaited.

+
+
+
+
+

Exception Propagation

+
+
+

Exceptions thrown inside a task are captured and rethrown when the task is awaited:

+
+
+
+
task<int> might_fail(bool should_fail)
+{
+    if (should_fail)
+        throw std::runtime_error("Operation failed");
+    co_return 42;
+}
+
+task<> example()
+{
+    try
+    {
+        int result = co_await might_fail(true);
+    }
+    catch (std::runtime_error const& e)
+    {
+        std::cout << "Caught: " << e.what() << "\n";
+    }
+}
+
+
+
+

The exception is stored in the promise when it occurs and rethrown in await_resume when the calling coroutine resumes.

+
+
+
+
+

Reference

+
+
+

The task<T> type is defined in:

+
+
+
+
#include <boost/capy/task.hpp>
+
+
+
+

Or included via the umbrella header:

+
+
+
+
#include <boost/capy.hpp>
+
+
+
+

You have now learned how to declare, return values from, and await task<T> coroutines. In the next section, you will learn how to launch tasks for execution using run_async and run.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4b.launching.html b/preview/4.coroutines/4b.launching.html new file mode 100644 index 0000000..c832672 --- /dev/null +++ b/preview/4.coroutines/4b.launching.html @@ -0,0 +1,638 @@ + + + + + + + + + + + + + + Launching Coroutines :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Launching Coroutines

+
+
+
+

This section explains how to launch coroutines for execution. You will learn about run_async for entry from non-coroutine code and run for executor hopping within coroutine code.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed The task Type

    +
  • +
  • +

    Understanding of lazy task execution

    +
  • +
+
+
+
+
+

The Execution Model

+
+
+

Capy tasks are lazy—they do not execute until something drives them. Two mechanisms exist:

+
+
+
    +
  • +

    Awaiting — One coroutine awaits another (co_await task)

    +
  • +
  • +

    Launching — Non-coroutine code initiates execution (run_async)

    +
  • +
+
+
+

When a task is awaited, the awaiting coroutine provides context: an executor for dispatching completion and a stop token for cancellation. But what about the first task in a chain? That task needs explicit launching.

+
+
+
+
+

run_async: Entry from Non-Coroutine Code

+
+
+

run_async is the bridge between regular code and coroutine code. It takes an executor, creates the necessary context, and starts the task executing.

+
+
+
+
#include <boost/capy.hpp>
+using namespace boost::capy;
+
+task<int> compute()
+{
+    co_return 42;
+}
+
+int main()
+{
+    thread_pool pool;
+    run_async(pool.get_executor())(compute());
+    // Task is now running on the thread pool
+
+    // pool destructor waits for work to complete
+    return 0;
+}
+
+
+
+

Two-Call Syntax

+
+

Notice the unusual syntax: run_async(executor)(task). This is intentional and relates to C++17 evaluation order.

+
+
+

C++17 guarantees that in the expression f(a)(b):

+
+
+
    +
  1. +

    f(a) is evaluated first, producing a callable

    +
  2. +
  3. +

    b is evaluated second

    +
  4. +
  5. +

    The callable is invoked with b

    +
  6. +
+
+
+

This ordering matters because the task’s coroutine frame is allocated during step 2, and run_async sets up thread-local allocator state in step 1. The task inherits that allocator.

+
+
+ + + + + +
+ + +
+

Do not store the result of run_async(executor) and call it later:

+
+
+
+
auto wrapper = run_async(pool.get_executor());  // Don't do this
+wrapper(compute());  // TLS state no longer valid
+
+
+
+

Always use the two-call pattern in a single expression.

+
+
+
+
+
+

Handler Overloads

+
+

run_async accepts optional handlers for results and exceptions:

+
+
+
+
// Result handler only (exceptions rethrown)
+run_async(ex, [](int result) {
+    std::cout << "Got: " << result << "\n";
+})(compute());
+
+// Separate handlers for result and exception
+run_async(ex,
+    [](int result) { std::cout << "Result: " << result << "\n"; },
+    [](std::exception_ptr ep) {
+        try { std::rethrow_exception(ep); }
+        catch (std::exception const& e) {
+            std::cout << "Error: " << e.what() << "\n";
+        }
+    }
+)(compute());
+
+
+
+

When no handlers are provided, results are discarded and exceptions are rethrown (causing std::terminate if uncaught).

+
+
+
+

Stop Token Support

+
+

Pass a stop token to enable cooperative cancellation:

+
+
+
+
std::stop_source source;
+run_async(ex, source.get_token())(cancellable_task());
+
+// Later, to request cancellation:
+source.request_stop();
+
+
+
+

The stop token is propagated to the task and all tasks it awaits.

+
+
+
+
+
+

run: Executor Hopping Within Coroutines

+
+
+

Inside a coroutine, use run to execute a child task on a different executor:

+
+
+
+
task<int> compute_on_pool(thread_pool& pool)
+{
+    // This task runs on whatever executor we're already on
+
+    // But this child task runs on the pool's executor:
+    int result = co_await run(pool.get_executor())(expensive_computation());
+
+    // After co_await, we're back on our original executor
+    co_return result;
+}
+
+
+
+

Executor Affinity

+
+

By default, a task inherits its caller’s executor. This means completions are dispatched through that executor, ensuring thread affinity for thread-sensitive code.

+
+
+

run overrides this inheritance for a specific child task, binding it to a different executor. The child task runs on the specified executor, and when it completes, the parent task resumes on its original executor.

+
+
+

This pattern is useful for:

+
+
+
    +
  • +

    Running CPU-intensive work on a thread pool

    +
  • +
  • +

    Performing I/O on an I/O-specific context

    +
  • +
  • +

    Ensuring UI updates happen on the UI thread

    +
  • +
+
+
+
+
+
+

Handler Threading

+
+
+

Handlers passed to run_async are invoked on whatever thread the executor schedules:

+
+
+
+
// If pool has 4 threads, the handler runs on one of those threads
+run_async(pool.get_executor(), [](int result) {
+    // This runs on a pool thread, NOT the main thread
+    update_shared_state(result);
+})(compute());
+
+
+
+

If you need results on a specific thread, use appropriate synchronization or dispatch mechanisms.

+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/ex/run_async.hpp>

Entry point for launching tasks from non-coroutine code

<boost/capy/ex/run.hpp>

Executor binding for child tasks within coroutines

+
+

You have now learned how to launch coroutines using run_async and bind child tasks to specific executors using run. In the next section, you will learn about executors and execution contexts in detail.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4c.executors.html b/preview/4.coroutines/4c.executors.html new file mode 100644 index 0000000..482dacc --- /dev/null +++ b/preview/4.coroutines/4c.executors.html @@ -0,0 +1,720 @@ + + + + + + + + + + + + + + Executors and Execution Contexts :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Executors and Execution Contexts

+
+
+
+

This section explains executors and execution contexts—the mechanisms that control where and how coroutines execute.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

The Executor Concept

+
+
+

An executor is an object that can schedule work for execution. In Capy, executors must provide two methods:

+
+
+
+
concept Executor = requires(E ex, std::coroutine_handle<> h) {
+    { ex.dispatch(h) } -> std::same_as<std::coroutine_handle<>>;
+    { ex.post(h) } -> std::same_as<void>;
+    { ex.context() } -> std::convertible_to<execution_context&>;
+};
+
+
+
+

dispatch() vs post()

+
+

Both methods schedule a coroutine for execution, but with different semantics:

+
+
+
+
dispatch(h)
+
+

May execute h inline if the current thread is already associated with the executor. Returns a coroutine handle—either h if execution was deferred, or std::noop_coroutine() if h was executed immediately. This enables symmetric transfer optimization.

+
+
post(h)
+
+

Always queues h for later execution. Never executes inline. Returns void. Use when you need guaranteed asynchrony.

+
+
+
+
+
+

context()

+
+

Returns a reference to the execution context that owns this executor. The context provides resources like frame allocators.

+
+
+
+
+
+

executor_ref: Type-Erased Executor

+
+
+

executor_ref wraps any executor in a type-erased container, allowing code to work with executors without knowing their concrete type:

+
+
+
+
void schedule_work(executor_ref ex, std::coroutine_handle<> h)
+{
+    ex.post(h);  // Works with any executor
+}
+
+int main()
+{
+    thread_pool pool;
+    executor_ref ex = pool.get_executor();  // Type erasure
+
+    schedule_work(ex, some_coroutine);
+}
+
+
+
+

executor_ref stores a reference to the underlying executor—the original executor must outlive the executor_ref.

+
+
+
+
+

thread_pool: Multi-Threaded Execution

+
+
+

thread_pool manages a pool of worker threads that execute coroutines concurrently:

+
+
+
+
#include <boost/capy/ex/thread_pool.hpp>
+
+int main()
+{
+    // Create pool with 4 threads
+    thread_pool pool(4);
+
+    // Get an executor for this pool
+    auto ex = pool.get_executor();
+
+    // Launch work on the pool
+    run_async(ex)(my_task());
+
+    // pool destructor waits for all work to complete
+}
+
+
+
+

Constructor Parameters

+
+
+
thread_pool(
+    std::size_t num_threads = 0,
+    std::string_view thread_name_prefix = "capy-pool-"
+);
+
+
+
+
    +
  • +

    num_threads — Number of worker threads. If 0, uses hardware concurrency.

    +
  • +
  • +

    thread_name_prefix — Prefix for thread names (useful for debugging).

    +
  • +
+
+
+
+

Thread Safety

+
+

Work posted to a thread_pool may execute on any of its worker threads. If your coroutines access shared data, you must use appropriate synchronization.

+
+
+
+
+
+

execution_context: Base Class

+
+
+

execution_context is the base class for execution contexts. It provides:

+
+
+
    +
  • +

    Frame allocator access via get_frame_allocator()

    +
  • +
  • +

    Service infrastructure for extensibility

    +
  • +
+
+
+

Custom execution contexts inherit from execution_context:

+
+
+
+
class my_context : public execution_context
+{
+public:
+    // ... custom implementation
+
+    my_executor get_executor();
+};
+
+
+
+
+
+

strand: Serialization Without Mutexes

+
+
+

A strand ensures that handlers are executed in order, with no two handlers executing concurrently. This eliminates the need for mutexes when all access to shared data goes through the strand.

+
+
+
+
#include <boost/capy/ex/strand.hpp>
+
+class shared_resource
+{
+    strand<thread_pool::executor_type> strand_;
+    int counter_ = 0;
+
+public:
+    explicit shared_resource(thread_pool& pool)
+        : strand_(pool.get_executor())
+    {
+    }
+
+    task<int> increment()
+    {
+        // All increments are serialized through the strand
+        co_return co_await run(strand_)(do_increment());
+    }
+
+private:
+    task<int> do_increment()
+    {
+        // No mutex needed—strand ensures exclusive access
+        ++counter_;
+        co_return counter_;
+    }
+};
+
+
+
+

How Strands Work

+
+

The strand maintains a queue of pending work. When work is dispatched:

+
+
+
    +
  1. +

    If no other work is executing on the strand, the new work runs immediately

    +
  2. +
  3. +

    If other work is executing, the new work is queued

    +
  4. +
  5. +

    When the current work completes, the next queued item runs

    +
  6. +
+
+
+

This provides logical single-threading without blocking physical threads.

+
+
+
+

When to Use Strands

+
+
    +
  • +

    Thread-affine resources — When code must not be called from multiple threads simultaneously

    +
  • +
  • +

    Ordered operations — When operations must complete in a specific order

    +
  • +
  • +

    Avoiding mutexes — When mutex overhead is unacceptable

    +
  • +
+
+
+
+
+
+

Single-Threaded vs Multi-Threaded Patterns

+
+
+

Single-Threaded

+
+

For single-threaded applications, use a context with one thread:

+
+
+
+
thread_pool single_thread(1);
+auto ex = single_thread.get_executor();
+// All work runs on the single thread
+
+
+
+
+

Multi-Threaded with Shared Data

+
+

For multi-threaded applications with shared data, use strands:

+
+
+
+
thread_pool pool(4);
+strand<thread_pool::executor_type> data_strand(pool.get_executor());
+
+// Use data_strand for all access to shared data
+// Use pool.get_executor() for independent work
+
+
+
+
+

Multi-Threaded with Independent Work

+
+

For embarrassingly parallel work with no shared state:

+
+
+
+
thread_pool pool(4);
+auto ex = pool.get_executor();
+
+// Launch independent tasks directly on the pool
+std::vector<task<int>> tasks;
+for (int i = 0; i < 100; ++i)
+    run_async(ex)(independent_task(i));
+
+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/concept/executor.hpp>

The Executor concept definition

<boost/capy/ex/executor_ref.hpp>

Type-erased executor wrapper

<boost/capy/ex/thread_pool.hpp>

Multi-threaded execution context

<boost/capy/ex/execution_context.hpp>

Base class for execution contexts

<boost/capy/ex/strand.hpp>

Serialization primitive

+
+

You have now learned about executors, execution contexts, thread pools, and strands. In the next section, you will learn about the IoAwaitable protocol that enables context propagation.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4d.io-awaitable.html b/preview/4.coroutines/4d.io-awaitable.html new file mode 100644 index 0000000..b6d7d73 --- /dev/null +++ b/preview/4.coroutines/4d.io-awaitable.html @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + The IoAwaitable Protocol :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

The IoAwaitable Protocol

+
+
+
+

This section explains the IoAwaitable protocol—Capy’s mechanism for propagating execution context through coroutine chains.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

The Problem: Context Propagation

+
+
+

Standard C++20 coroutines define awaiters with this await_suspend signature:

+
+
+
+
void await_suspend(std::coroutine_handle<> h);
+// or
+bool await_suspend(std::coroutine_handle<> h);
+// or
+std::coroutine_handle<> await_suspend(std::coroutine_handle<> h);
+
+
+
+

The awaiter receives only a handle to the suspended coroutine. But real I/O code needs more:

+
+
+
    +
  • +

    Executor — Where should completions be dispatched?

    +
  • +
  • +

    Stop token — Should this operation support cancellation?

    +
  • +
  • +

    Allocator — Where should memory be allocated?

    +
  • +
+
+
+

How does an awaitable get this information?

+
+
+

Backward Query Approach

+
+

One approach: the awaitable queries the calling coroutine’s promise for context. This requires the awaitable to know the promise type, creating tight coupling.

+
+
+
+

Forward Propagation Approach

+
+

Capy uses forward propagation: the caller passes context to the awaitable through an extended await_suspend signature.

+
+
+
+
+
+

The Two-Argument await_suspend

+
+
+

The IoAwaitable protocol extends await_suspend to receive context:

+
+
+
+
std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, io_env const* env);
+
+
+
+

This signature receives:

+
+
+
    +
  • +

    h — The coroutine handle (as in standard awaiters)

    +
  • +
  • +

    env — The execution environment containing:

    +
    +
      +
    • +

      env→executor — The caller’s executor for dispatching completions

      +
    • +
    • +

      env→stop_token — A stop token for cooperative cancellation

      +
    • +
    • +

      env→allocator — An optional allocator for frame allocation

      +
    • +
    +
    +
  • +
+
+
+

The return type enables symmetric transfer.

+
+
+
+
+

IoAwaitable Concept

+
+
+

An awaitable satisfies IoAwaitable if:

+
+
+
+
template<typename T>
+concept IoAwaitable = requires(T& t, std::coroutine_handle<> h, io_env const* env) {
+    { t.await_ready() } -> std::convertible_to<bool>;
+    { t.await_suspend(h, env) } -> std::same_as<std::coroutine_handle<>>;
+    t.await_resume();
+};
+
+
+
+

The key difference from standard awaitables is the two-argument await_suspend that receives the io_env.

+
+
+
+
+

IoRunnable Concept

+
+
+

For tasks that can be launched from non-coroutine contexts, the IoRunnable concept refines IoAwaitable with:

+
+
+
    +
  • +

    handle() — Access the typed coroutine handle

    +
  • +
  • +

    release() — Transfer ownership of the frame

    +
  • +
  • +

    exception() — Check for captured exceptions

    +
  • +
  • +

    result() — Access the result value (non-void tasks)

    +
  • +
+
+
+

These methods exist because launch functions like run_async cannot co_await the task directly. The trampoline must be allocated before the task type is known, so it type-erases the task through function pointers and needs a common API to manage lifetime and extract results.

+
+
+

Context injection methods (set_environment, set_continuation) are internal to the promise and not part of any concept. Launch functions access them through the typed handle provided by handle().

+
+
+

Capy’s task<T> satisfies this concept.

+
+
+
+
+

How Context Flows

+
+
+

When you write co_await child_task() inside a task<T>:

+
+
+
    +
  1. +

    The parent task’s await_transform intercepts the awaitable

    +
  2. +
  3. +

    It wraps the child in a transform awaiter

    +
  4. +
  5. +

    The transform awaiter’s await_suspend passes context:

    +
  6. +
+
+
+
+
template<class Awaitable>
+auto await_suspend(std::coroutine_handle<Promise> h)
+{
+    // Forward caller's context to child
+    return awaitable_.await_suspend(h, promise_.environment());
+}
+
+
+
+

The child receives the parent’s executor and stop token automatically.

+
+
+
+
+

Why Forward Propagation?

+
+
+

Forward propagation offers several advantages:

+
+
+
    +
  • +

    Decoupling — Awaitables don’t need to know caller’s promise type

    +
  • +
  • +

    Composability — Any IoAwaitable works with any IoRunnable task

    +
  • +
  • +

    Explicit flow — Context flows downward through the call chain, not queried upward

    +
  • +
+
+
+

This design enables Capy’s type-erased wrappers (any_stream, etc.) to work without knowing the concrete executor type.

+
+
+
+
+

Implementing Custom IoAwaitables

+
+
+

To create a custom IoAwaitable:

+
+
+
+
struct my_awaitable
+{
+    io_env const* env_ = nullptr;
+    std::coroutine_handle<> continuation_;
+    result_type result_;
+
+    bool await_ready() const noexcept
+    {
+        return false;  // Or true if result is immediately available
+    }
+
+    std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, io_env const* env)
+    {
+        // Store pointer to environment, never copy
+        env_ = env;
+        continuation_ = h;
+
+        // Start async operation...
+        start_operation();
+
+        // Return noop to suspend
+        return std::noop_coroutine();
+    }
+
+    result_type await_resume()
+    {
+        return result_;
+    }
+
+private:
+    void on_completion()
+    {
+        // Resume on caller's executor
+        env_->executor.dispatch(continuation_);
+    }
+};
+
+
+
+

The key points:

+
+
+
    +
  1. +

    Store the io_env as a pointer (io_env const*), never a copy. Launch functions guarantee the io_env outlives the awaitable’s operation.

    +
  2. +
  3. +

    Use the executor to dispatch completion

    +
  4. +
  5. +

    Respect the stop token for cancellation

    +
  6. +
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/concept/io_awaitable.hpp>

The IoAwaitable concept definition

<boost/capy/concept/io_runnable.hpp>

The IoRunnable concept for launchable tasks

+
+

You have now learned how the IoAwaitable protocol enables context propagation through coroutine chains. In the next section, you will learn about stop tokens and cooperative cancellation.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4e.cancellation.html b/preview/4.coroutines/4e.cancellation.html new file mode 100644 index 0000000..bf4bce1 --- /dev/null +++ b/preview/4.coroutines/4e.cancellation.html @@ -0,0 +1,953 @@ + + + + + + + + + + + + + + Stop Tokens and Cancellation :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Stop Tokens and Cancellation

+
+
+
+

This section teaches cooperative cancellation from the ground up, explaining C++20 stop tokens as a general-purpose notification mechanism and how Capy uses them for coroutine cancellation.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Part 1: The Problem

+
+
+

Cancellation matters in many scenarios:

+
+
+
    +
  • +

    A user clicks "Cancel" on a download dialog

    +
  • +
  • +

    A timeout expires while waiting for a network response

    +
  • +
  • +

    A connection drops unexpectedly

    +
  • +
  • +

    An application is shutting down

    +
  • +
+
+
+

The Naive Approach: Boolean Flags

+
+

The obvious solution seems to be a boolean flag:

+
+
+
+
std::atomic<bool> should_cancel{false};
+
+void worker()
+{
+    while (!should_cancel)
+    {
+        do_work();
+    }
+}
+
+
+
+

This approach has problems:

+
+
+
    +
  • +

    No standardization — Every component invents its own cancellation flag

    +
  • +
  • +

    Race conditions — Checking the flag and acting on it is not atomic

    +
  • +
  • +

    No cleanup notification — The worker just stops; no opportunity for graceful cleanup

    +
  • +
  • +

    Polling overhead — Must check the flag repeatedly

    +
  • +
+
+
+
+

The Thread Interruption Problem

+
+

Some systems support forceful thread interruption. This is dangerous because it can leave resources in inconsistent states—files half-written, locks held, transactions uncommitted.

+
+
+
+

The Goal: Cooperative Cancellation

+
+

The solution is cooperative cancellation: ask nicely, let the work clean up. The cancellation requestor signals intent; the worker decides when and how to respond.

+
+
+
+
+
+

Part 2: C++20 Stop Tokens—A General-Purpose Signaling Mechanism

+
+
+

C++20 introduces std::stop_token, std::stop_source, and std::stop_callback. While named for "stopping," these implement a general-purpose Observer pattern—a thread-safe one-to-many notification system.

+
+
+

The Three Components

+
+
+
std::stop_source
+
+

The Subject/Publisher. Owns the shared state and can trigger notifications. Create one source, then distribute tokens to observers.

+
+
std::stop_token
+
+

The Subscriber View. A read-only, copyable, cheap-to-pass-around handle. Multiple tokens can share the same underlying state.

+
+
std::stop_callback<F>
+
+

The Observer Registration. An RAII object that registers a callback to run when signaled. Destruction automatically unregisters.

+
+
+
+
+
+

How They Work Together

+
+
+
#include <stop_token>
+#include <iostream>
+
+void example()
+{
+    std::stop_source source;
+
+    // Create tokens (distribute notification capability)
+    std::stop_token token1 = source.get_token();
+    std::stop_token token2 = source.get_token();  // Same underlying state
+
+    // Register callbacks (observers)
+    std::stop_callback cb1(token1, []{ std::cout << "Observer 1 notified\n"; });
+    std::stop_callback cb2(token2, []{ std::cout << "Observer 2 notified\n"; });
+
+    std::cout << "Before signal\n";
+    source.request_stop();  // Triggers all callbacks
+    std::cout << "After signal\n";
+}
+
+
+
+

Output:

+
+
+
+
Before signal
+Observer 1 notified
+Observer 2 notified
+After signal
+
+
+
+
+

Immediate Invocation

+
+

If a callback is registered after request_stop() was already called, the callback runs immediately in the constructor:

+
+
+
+
std::stop_source source;
+source.request_stop();  // Already signaled
+
+// Callback runs in constructor, not later
+std::stop_callback cb(source.get_token(), []{
+    std::cout << "Runs immediately!\n";
+});
+
+
+
+

This ensures observers never miss the signal, regardless of registration timing.

+
+
+
+

Type-Erased Polymorphic Observers

+
+

Each stop_callback<F> stores a different callable type F. Despite this, all callbacks for a given source can be invoked uniformly. This is equivalent to having vector<function<void()>> but with:

+
+
+
    +
  • +

    No heap allocation per callback

    +
  • +
  • +

    No virtual function overhead

    +
  • +
  • +

    RAII lifetime management

    +
  • +
+
+
+
+

Thread Safety

+
+

Registration and invocation are thread-safe. You can register callbacks, request stop, and invoke callbacks from any thread without additional synchronization.

+
+
+
+
+
+

Part 3: The One-Shot Nature

+
+
+ + + + + +
+ + +
+

Critical limitation: stop_token is a one-shot mechanism.

+
+
+
    +
  • +

    Can only transition from "not signaled" to "signaled" once

    +
  • +
  • +

    No reset mechanism—once stop_requested() returns true, it stays true forever

    +
  • +
  • +

    request_stop() returns true only on the first successful call

    +
  • +
  • +

    You cannot "un-cancel" a stop_source

    +
  • +
+
+
+
+
+

Why This Matters

+
+

If you design a system that needs to cancel and restart operations, you cannot reuse the same stop_source. Each cycle requires a fresh source and fresh tokens.

+
+
+
+

The Reset Workaround

+
+

To "reset," create an entirely new stop_source:

+
+
+
+
std::stop_source source;
+auto token = source.get_token();
+
+// ... distribute token to workers ...
+
+source.request_stop();  // Triggered, now permanently signaled
+
+// To "reset": create new source
+source = std::stop_source{};  // New shared state
+// Old tokens are now orphaned (stop_possible() returns false)
+
+// Must redistribute new tokens to ALL holders of the old token
+auto new_token = source.get_token();
+
+
+
+

This is manual and error-prone. Any code still holding the old token will not receive new signals.

+
+
+
+

Design Implication

+
+

If you need repeatable signals, stop_token is the wrong tool. Consider:

+
+
+
    +
  • +

    Condition variables for repeatable wake-ups

    +
  • +
  • +

    Atomic flags with explicit reset protocol

    +
  • +
  • +

    Custom event types

    +
  • +
+
+
+
+
+
+

Part 4: Beyond Cancellation

+
+
+

The "stop" naming obscures the mechanism’s generality. stop_token implements one-shot broadcast notification, useful for:

+
+
+
    +
  • +

    Starting things — Signal "ready" to trigger initialization

    +
  • +
  • +

    Configuration loaded — Notify components when config is available

    +
  • +
  • +

    Resource availability — Signal when database connected or cache warmed

    +
  • +
  • +

    Any one-shot broadcast scenario

    +
  • +
+
+
+
+
+

Part 5: Stop Tokens in Coroutines

+
+
+

Coroutines have a propagation problem: how does a nested coroutine know to stop? If you pass a stop token explicitly to every function, your APIs become cluttered.

+
+
+

Capy’s Answer: Automatic Propagation

+
+

Capy propagates stop tokens downward through co_await. When you await a task, the IoAwaitable protocol passes the current stop token to the child:

+
+
+
+
task<> parent()
+{
+    // Our stop token is automatically passed to child
+    co_await child();
+}
+
+task<> child()
+{
+    // Receives parent's stop token via IoAwaitable protocol
+    auto token = co_await get_stop_token();  // Access current token
+}
+
+
+
+

No manual threading—the protocol handles it.

+
+
+
+

Accessing the Stop Token

+
+

Inside a task, use get_stop_token() to access the current stop token:

+
+
+
+
task<> cancellable_work()
+{
+    auto token = co_await get_stop_token();
+
+    while (!token.stop_requested())
+    {
+        co_await do_chunk_of_work();
+    }
+}
+
+
+
+
+
+
+

Part 6: Responding to Cancellation

+
+
+

Checking the Token

+
+
+
task<> process_items(std::vector<Item> const& items)
+{
+    auto token = co_await get_stop_token();
+
+    for (auto const& item : items)
+    {
+        if (token.stop_requested())
+            co_return;  // Exit early
+
+        co_await process(item);
+    }
+}
+
+
+
+
+

Cleanup with RAII

+
+

RAII ensures resources are released on early exit:

+
+
+
+
task<> with_resource()
+{
+    auto resource = acquire_resource();  // RAII wrapper
+    auto token = co_await get_stop_token();
+
+    while (!token.stop_requested())
+    {
+        co_await use_resource(resource);
+    }
+    // resource destructor runs regardless of how we exit
+}
+
+
+
+
+

The operation_aborted Convention

+
+

When cancellation causes an operation to fail, the conventional error code is error::operation_aborted:

+
+
+
+
task<std::string> fetch_with_cancel()
+{
+    auto token = co_await get_stop_token();
+
+    if (token.stop_requested())
+    {
+        throw std::system_error(
+            make_error_code(std::errc::operation_canceled));
+    }
+
+    co_return co_await do_fetch();
+}
+
+
+
+
+
+
+

Part 7: OS Integration

+
+
+

Capy’s I/O operations (provided by Corosio) respect stop tokens at the OS level:

+
+
+
    +
  • +

    IOCP (Windows) — Pending operations can be cancelled via CancelIoEx

    +
  • +
  • +

    io_uring (Linux) — Operations can be cancelled via IORING_OP_ASYNC_CANCEL

    +
  • +
+
+
+

When you request stop, pending I/O operations are cancelled at the OS level, providing immediate response rather than waiting for the operation to complete naturally.

+
+
+
+
+

Part 8: Patterns

+
+
+

Timeout Pattern

+
+

Combine a timer with stop token to implement timeouts:

+
+
+
+
task<> with_timeout(task<> operation, std::chrono::seconds timeout)
+{
+    std::stop_source source;
+
+    // Timer that requests stop after timeout
+    auto timer = co_await start_timer(timeout, [&source] {
+        source.request_stop();
+    });
+
+    // Run operation with our stop token
+    co_await run_with_token(source.get_token(), std::move(operation));
+}
+
+
+
+
+

User Cancellation

+
+

Connect UI cancellation to stop tokens:

+
+
+
+
class download_manager
+{
+    std::stop_source stop_source_;
+
+public:
+    void start_download(std::string url)
+    {
+        run_async(executor_)(download(url, stop_source_.get_token()));
+    }
+
+    void cancel()
+    {
+        stop_source_.request_stop();
+    }
+};
+
+
+
+
+

Graceful Shutdown

+
+

Cancel all pending work during shutdown:

+
+
+
+
class server
+{
+    std::stop_source shutdown_source_;
+
+public:
+    void shutdown()
+    {
+        shutdown_source_.request_stop();
+        // All pending operations receive stop request
+    }
+
+    task<> handle_connection(connection conn)
+    {
+        auto token = shutdown_source_.get_token();
+
+        while (!token.stop_requested())
+        {
+            co_await process_request(conn);
+        }
+
+        // Graceful cleanup
+        co_await send_goodbye(conn);
+    }
+};
+
+
+
+
+

when_any Cancellation

+
+

when_any uses stop tokens internally to cancel "losing" tasks when the first task completes. This is covered in Concurrent Composition.

+
+
+
+
+
+

Reference

+
+
+

The stop token mechanism is part of the C++ standard library:

+
+
+
+
#include <stop_token>
+
+
+
+

Key types:

+
+
+
    +
  • +

    std::stop_source — Creates and manages stop state

    +
  • +
  • +

    std::stop_token — Observes stop state

    +
  • +
  • +

    std::stop_callback<F> — Registers callbacks for stop notification

    +
  • +
+
+
+

You have now learned how stop tokens provide cooperative cancellation for coroutines. In the next section, you will learn about concurrent composition with when_all and when_any.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4f.composition.html b/preview/4.coroutines/4f.composition.html new file mode 100644 index 0000000..f35451e --- /dev/null +++ b/preview/4.coroutines/4f.composition.html @@ -0,0 +1,734 @@ + + + + + + + + + + + + + + Concurrent Composition :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Concurrent Composition

+
+
+
+

This section explains how to run multiple tasks concurrently using when_all and when_any.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Overview

+
+
+

Sequential execution—one task after another—is the default when using co_await:

+
+
+
+
task<> sequential()
+{
+    co_await task_a();  // Wait for A
+    co_await task_b();  // Then wait for B
+    co_await task_c();  // Then wait for C
+}
+
+
+
+

For independent operations, concurrent execution is more efficient:

+
+
+
+
task<> concurrent()
+{
+    // Run A, B, C simultaneously
+    co_await when_all(task_a(), task_b(), task_c());
+}
+
+
+
+
+
+

when_all: Wait for All Tasks

+
+
+

when_all launches multiple tasks concurrently and waits for all of them to complete:

+
+
+
+
#include <boost/capy/when_all.hpp>
+
+task<int> fetch_a() { co_return 1; }
+task<int> fetch_b() { co_return 2; }
+task<std::string> fetch_c() { co_return "hello"; }
+
+task<> example()
+{
+    auto [a, b, c] = co_await when_all(fetch_a(), fetch_b(), fetch_c());
+
+    // a == 1
+    // b == 2
+    // c == "hello"
+}
+
+
+
+

Result Tuple

+
+

when_all returns a tuple of results in the same order as the input tasks. Use structured bindings to unpack them.

+
+
+
+

Void Filtering

+
+

Tasks returning void do not contribute to the result tuple:

+
+
+
+
task<> void_task() { co_return; }
+task<int> int_task() { co_return 42; }
+
+task<> example()
+{
+    auto [value] = co_await when_all(void_task(), int_task(), void_task());
+    // value == 42  (only the int_task contributes)
+}
+
+
+
+

If all tasks return void, when_all returns void:

+
+
+
+
task<> example()
+{
+    co_await when_all(void_task_a(), void_task_b());  // Returns void
+}
+
+
+
+
+

Error Handling

+
+

If any task throws an exception:

+
+
+
    +
  1. +

    The exception is captured

    +
  2. +
  3. +

    Stop is requested for sibling tasks

    +
  4. +
  5. +

    All tasks are allowed to complete (or respond to stop)

    +
  6. +
  7. +

    The first exception is rethrown; later exceptions are discarded

    +
  8. +
+
+
+
+
task<int> might_fail(bool fail)
+{
+    if (fail)
+        throw std::runtime_error("failed");
+    co_return 42;
+}
+
+task<> example()
+{
+    try
+    {
+        co_await when_all(might_fail(true), might_fail(false));
+    }
+    catch (std::runtime_error const& e)
+    {
+        // Catches the exception from the failing task
+    }
+}
+
+
+
+
+

Stop Propagation

+
+

When one task fails, when_all requests stop for its siblings. Well-behaved tasks should check their stop token and exit promptly:

+
+
+
+
task<> long_running()
+{
+    auto token = co_await get_stop_token();
+
+    for (int i = 0; i < 1000; ++i)
+    {
+        if (token.stop_requested())
+            co_return;  // Exit early when sibling fails
+
+        co_await do_iteration();
+    }
+}
+
+
+
+
+
+
+

when_any: First-to-Finish Wins

+
+
+

when_any launches multiple tasks concurrently and returns when the first one completes:

+
+
+
+
#include <boost/capy/when_any.hpp>
+
+task<> example()
+{
+    auto [index, result] = co_await when_any(
+        fetch_int(),     // task<int>
+        fetch_string()   // task<std::string>
+    );
+    // index indicates which task won (0 or 1)
+    // result is std::variant<int, std::string>
+}
+
+
+
+

The result is a pair containing the winner’s index and a deduplicated variant of possible result types. When a winner is determined, stop is requested for all siblings. All tasks complete before when_any returns.

+
+
+

For detailed coverage including error handling, cancellation, and the vector overload, see Racing Tasks.

+
+
+
+
+

Practical Patterns

+
+
+

Parallel Fetch

+
+

Fetch multiple resources simultaneously:

+
+
+
+
task<page_data> fetch_page_data(std::string url)
+{
+    auto [header, body, sidebar] = co_await when_all(
+        fetch_header(url),
+        fetch_body(url),
+        fetch_sidebar(url)
+    );
+
+    co_return page_data{
+        std::move(header),
+        std::move(body),
+        std::move(sidebar)
+    };
+}
+
+
+
+
+

Fan-Out/Fan-In

+
+

Process items in parallel, then combine results:

+
+
+
+
task<int> process_item(item const& i);
+
+task<int> process_all(std::vector<item> const& items)
+{
+    std::vector<task<int>> tasks;
+    for (auto const& item : items)
+        tasks.push_back(process_item(item));
+
+    // This requires a range-based when_all (not yet available)
+    // For now, use fixed-arity when_all
+
+    int total = 0;
+    // ... accumulate results
+    co_return total;
+}
+
+
+
+
+

Timeout with Fallback

+
+

Use when_any to implement timeout with fallback:

+
+
+
+
task<Response> fetch_with_timeout(Request req)
+{
+    auto [index, result] = co_await when_any(
+        fetch_data(req),
+        timeout_after<Response>(100ms)
+    );
+
+    if (index == 1)
+        throw timeout_error{"Request timed out"};
+
+    co_return std::get<Response>(result);
+}
+
+
+
+

The timeout_after helper waits for the specified duration then throws. If fetch_data completes first, its result is returned. If the timer wins, the timeout exception propagates.

+
+
+
+
+
+

Implementation Notes

+
+
+

Task Storage

+
+

when_all stores all tasks in its coroutine frame. Tasks are moved from the arguments, so the original task objects become empty after the call.

+
+
+
+

Completion Tracking

+
+

A shared atomic counter tracks how many tasks remain. Each task completion decrements the counter. When it reaches zero, the parent coroutine is resumed.

+
+
+
+

Runner Coroutines

+
+

Each child task is wrapped in a "runner" coroutine that:

+
+
+
    +
  1. +

    Receives context (executor, stop token) from when_all

    +
  2. +
  3. +

    Awaits the child task

    +
  4. +
  5. +

    Stores the result in shared state

    +
  6. +
  7. +

    Signals completion

    +
  8. +
+
+
+

This design ensures proper context propagation to all children.

+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/when_all.hpp>

Concurrent composition with when_all

<boost/capy/when_any.hpp>

First-completion racing with when_any

+
+

You have now learned how to compose tasks concurrently with when_all and when_any. In the next section, you will learn about frame allocators for customizing coroutine memory allocation.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/4.coroutines/4g.allocators.html b/preview/4.coroutines/4g.allocators.html new file mode 100644 index 0000000..06cfddc --- /dev/null +++ b/preview/4.coroutines/4g.allocators.html @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + Frame Allocators :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Frame Allocators

+
+
+
+

This section explains how coroutine frames are allocated and how to customize allocation for performance.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

The Timing Constraint

+
+
+

Coroutine frame allocation has a unique constraint: memory must be allocated before the coroutine body begins executing. The standard C++ mechanism—promise type’s operator new—is called before the promise is constructed.

+
+
+

This creates a challenge: how can a coroutine use a custom allocator when the allocator might be passed as a parameter, which is stored in the frame?

+
+
+
+
+

Thread-Local Propagation

+
+
+

Capy solves this with thread-local propagation:

+
+
+
    +
  1. +

    Before evaluating the task argument, run_async sets a thread-local allocator

    +
  2. +
  3. +

    The task’s operator new reads this thread-local allocator

    +
  4. +
  5. +

    The task stores the allocator in its promise for child propagation

    +
  6. +
+
+
+

This is why run_async uses two-call syntax:

+
+
+
+
run_async(executor)(my_task());
+//        ↑         ↑
+//        1. Sets    2. Task allocated
+//        TLS        using TLS allocator
+
+
+
+
+
+

The Window

+
+
+

The "window" is the interval between setting the thread-local allocator and the coroutine’s first suspension point. During this window:

+
+
+
    +
  • +

    The task is allocated using the TLS allocator

    +
  • +
  • +

    The task captures the TLS allocator in its promise

    +
  • +
  • +

    Child tasks inherit the allocator

    +
  • +
+
+
+

After the window closes (at the first suspension), the TLS allocator may be restored to a previous value. The task retains its captured allocator regardless.

+
+
+
+
+

The FrameAllocator Concept

+
+
+

Custom allocators must satisfy the FrameAllocator concept, which is compatible with C++ allocator requirements:

+
+
+
+
template<typename A>
+concept FrameAllocator = requires {
+    typename A::value_type;
+} && requires(A& a, std::size_t n) {
+    { a.allocate(n) } -> std::same_as<typename A::value_type*>;
+    { a.deallocate(std::declval<typename A::value_type*>(), n) };
+};
+
+
+
+

In practice, any standard allocator works.

+
+
+
+
+

Using Custom Allocators

+
+
+

With run_async

+
+

Pass an allocator to run_async:

+
+
+
+
std::pmr::monotonic_buffer_resource resource;
+std::pmr::polymorphic_allocator<std::byte> alloc(&resource);
+
+run_async(executor, alloc)(my_task());
+
+
+
+

Or pass a memory_resource* directly:

+
+
+
+
std::pmr::monotonic_buffer_resource resource;
+run_async(executor, &resource)(my_task());
+
+
+
+
+

Default Allocator

+
+

When no allocator is specified, run_async uses the execution context’s default frame allocator, typically a recycling allocator optimized for coroutine frame sizes.

+
+
+
+
+
+

Recycling Allocator

+
+
+

Capy provides recycling_memory_resource, a memory resource optimized for coroutine frames:

+
+
+
    +
  • +

    Maintains freelists by size class

    +
  • +
  • +

    Reuses recently freed blocks (cache-friendly)

    +
  • +
  • +

    Falls back to upstream allocator for new sizes

    +
  • +
+
+
+

This allocator is used by default for thread_pool and other execution contexts.

+
+
+
+
+

HALO Optimization

+
+
+

Heap Allocation eLision Optimization (HALO) allows the compiler to allocate coroutine frames on the stack instead of the heap when:

+
+
+
    +
  • +

    The coroutine’s lifetime is provably contained in the caller’s

    +
  • +
  • +

    The frame size is known at compile time

    +
  • +
  • +

    Optimization is enabled

    +
  • +
+
+
+

Capy’s task<T> uses the attribute (when available) to enable HALO:

+
+
+
+
template<typename T = void>
+struct [[nodiscard]] BOOST_CAPY_CORO_AWAIT_ELIDABLE
+    task
+{
+    // ...
+};
+
+
+
+

When HALO Applies

+
+

HALO is most effective for immediately-awaited tasks:

+
+
+
+
// HALO can apply: task is awaited immediately
+int result = co_await compute();
+
+// HALO cannot apply: task escapes to storage
+auto t = compute();
+tasks.push_back(std::move(t));
+
+
+
+
+

Measuring HALO Effectiveness

+
+

Profile your application to see if HALO is taking effect. Look for:

+
+
+
    +
  • +

    Reduced heap allocations

    +
  • +
  • +

    Improved cache locality

    +
  • +
  • +

    Lower allocation latency

    +
  • +
+
+
+
+
+
+

Best Practices

+
+
+

Use Default Allocators

+
+

For most applications, the default recycling allocator provides good performance without configuration.

+
+
+
+

Consider Memory Resources for Batched Work

+
+

When launching many short-lived tasks together, a monotonic buffer resource can be efficient:

+
+
+
+
void process_batch(std::vector<item> const& items)
+{
+    std::array<std::byte, 64 * 1024> buffer;
+    std::pmr::monotonic_buffer_resource resource(
+        buffer.data(), buffer.size());
+
+    for (auto const& item : items)
+    {
+        run_async(executor, &resource)(process(item));
+    }
+    // All frames deallocated when resource goes out of scope
+}
+
+
+
+
+

Profile Before Optimizing

+
+

Coroutine frame allocation is rarely the bottleneck. Profile your application before investing in custom allocators.

+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/ex/frame_allocator.hpp>

Frame allocator concept and utilities

<boost/capy/ex/recycling_memory_resource.hpp>

Default recycling allocator implementation

+
+

You have now learned how coroutine frame allocation works and how to customize it. This completes the Coroutines in Capy section. Continue to Buffer Sequences to learn about Capy’s buffer model.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5.intro.html b/preview/5.buffers/5.intro.html new file mode 100644 index 0000000..b2ce4ae --- /dev/null +++ b/preview/5.buffers/5.intro.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + Buffer Sequences :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Buffer Sequences

+
+

Every I/O operation ultimately comes down to moving bytes between your program and the outside world—​a socket, a file, a pipe. The question is: how do you describe where those bytes live in memory?

+
+
+

The obvious answer is a pointer and a size. And for a single contiguous buffer, that works. But real I/O is rarely that tidy. An HTTP response has headers in one buffer and a body in another. A message might be assembled from a protocol header, a payload, and a checksum—​each produced by different parts of your code, each sitting in its own memory. The operating system even supports scatter/gather I/O specifically to handle this: a single system call that reads into or writes from multiple non-contiguous buffers.

+
+
+

Capy’s buffer model is designed for this reality. Instead of forcing you to copy data into a single contiguous allocation, Capy uses buffer sequences--lightweight, zero-copy abstractions that let you describe any arrangement of memory and pass it directly to the OS. The design is concept-driven, meaning the compiler verifies correctness at compile time with no runtime overhead.

+
+
+

This section covers everything you need to work with memory in Capy’s I/O model. You will learn the fundamental buffer types, how to compose them into sequences for scatter/gather I/O, and how they map to operating system primitives. You will also meet the algorithms that manipulate buffer data and the dynamic buffer abstractions that grow as data arrives. Understanding buffers is essential for everything that follows—​streams, I/O operations, and protocol implementations all build on the abstractions introduced here.

+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5a.overview.html b/preview/5.buffers/5a.overview.html new file mode 100644 index 0000000..ec639d2 --- /dev/null +++ b/preview/5.buffers/5a.overview.html @@ -0,0 +1,670 @@ + + + + + + + + + + + + + + Why Concepts, Not Spans :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Why Concepts, Not Spans

+
+
+
+

This section explains why Capy uses concept-driven buffer sequences instead of std::span, and why this design enables composition without allocation.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Basic C++ experience with memory and pointers

    +
  • +
  • +

    Familiarity with C++20 concepts

    +
  • +
+
+
+
+
+

The I/O Use Case

+
+
+

Buffers exist to interface with operating system I/O. When you read from a socket, write to a file, or transfer data through any I/O channel, you work with contiguous memory regions—addresses and byte counts.

+
+
+

The fundamental unit is a (pointer, size) pair. The OS reads bytes from or writes bytes to linear addresses.

+
+
+
+
+

The Reflexive Answer: span

+
+
+

The instinctive C++ answer to "how should I represent a buffer?" is std::span<std::byte>:

+
+
+
+
void write_data(std::span<std::byte const> data);
+void read_data(std::span<std::byte> buffer);
+
+
+
+

This works for single contiguous buffers. But I/O often involves multiple buffers—a technique called scatter/gather I/O.

+
+
+
+
+

Scatter/Gather I/O

+
+
+

Consider assembling an HTTP message. The headers are in one buffer; the body is in another. With single-buffer APIs, you must:

+
+
+
    +
  1. +

    Allocate a new buffer large enough for both

    +
  2. +
  3. +

    Copy headers into the new buffer

    +
  4. +
  5. +

    Copy body after headers

    +
  6. +
  7. +

    Send the combined buffer

    +
  8. +
+
+
+

This is wasteful. The data already exists—why copy it?

+
+
+

Scatter/gather I/O solves this. Operating systems provide vectored I/O calls (writev on POSIX, scatter/gather with IOCP on Windows) that accept multiple buffers and transfer them as a single logical operation.

+
+
+
+
+

The Span Reflex for Multiple Buffers

+
+
+

Extending the span reflex: std::span<std::span<std::byte>>:

+
+
+
+
void write_data(std::span<std::span<std::byte const> const> buffers);
+
+
+
+

This works, but introduces a composition problem.

+
+
+
+
+

The Composition Problem

+
+
+

Suppose you have:

+
+
+
+
using HeaderBuffers = std::array<std::span<std::byte const>, 2>;  // 2 buffers
+using BodyBuffers = std::array<std::span<std::byte const>, 3>;    // 3 buffers
+
+
+
+

To send headers followed by body, you need 5 buffers total. With span<span<byte>>:

+
+
+
+
HeaderBuffers headers = /* ... */;
+BodyBuffers body = /* ... */;
+
+// To combine, you MUST allocate a new array:
+std::array<std::span<std::byte const>, 5> combined;
+std::copy(headers.begin(), headers.end(), combined.begin());
+std::copy(body.begin(), body.end(), combined.begin() + 2);
+
+write_data(combined);
+
+
+
+

Every composition allocates. This leads to:

+
+
+
    +
  • +

    Overload proliferation—separate functions for single buffer, multiple buffers, common cases

    +
  • +
  • +

    Performance overhead—allocation on every composition

    +
  • +
  • +

    Boilerplate—manual copying everywhere

    +
  • +
+
+
+
+
+

The Concept-Driven Alternative

+
+
+

Instead of concrete types, use concepts. Define ConstBufferSequence as "any type that can produce a sequence of buffers":

+
+
+
+
template<ConstBufferSequence Buffers>
+void write_data(Buffers const& buffers);
+
+
+
+

This single signature accepts:

+
+
+
    +
  • +

    A single const_buffer

    +
  • +
  • +

    A span<const_buffer>

    +
  • +
  • +

    A vector<const_buffer>

    +
  • +
  • +

    A string_view (converts to single buffer)

    +
  • +
  • +

    A custom composite type

    +
  • +
  • +

    Any composition of the above—without allocation

    +
  • +
+
+
+
+
+

Zero-Allocation Composition

+
+
+

With concepts, composition creates views, not copies:

+
+
+
+
HeaderBuffers headers = /* ... */;
+BodyBuffers body = /* ... */;
+
+// cat() creates a view that iterates both sequences
+auto combined = cat(headers, body);  // No allocation!
+
+write_data(combined);  // Works because combined satisfies ConstBufferSequence
+
+
+
+

The cat function returns a lightweight object that, when iterated, first yields buffers from headers, then from body. The buffers themselves are not copied—only iterators are composed.

+
+
+
+
+

STL Parallel

+
+
+

This design follows Stepanov’s insight from the STL: algorithms parameterized on concepts (iterators), not concrete types (containers), enable composition that concrete types forbid.

+
+
+

The span reflex is a regression from thirty years of generic programming. Concepts restore the compositional power that concrete types lack.

+
+
+
+
+

The Middle Ground

+
+
+

Concepts provide flexibility at user-facing APIs. But at type-erasure boundaries—virtual functions, library boundaries—concrete types are necessary.

+
+
+

Capy’s approach:

+
+
+
    +
  • +

    User-facing APIs — Accept concepts for maximum flexibility

    +
  • +
  • +

    Type-erasure boundaries — Use concrete spans internally

    +
  • +
  • +

    Library handles conversion — Users get concepts; implementation uses spans

    +
  • +
+
+
+

This gives users the composition benefits of concepts while hiding the concrete types needed for virtual dispatch.

+
+
+
+
+

Why Not std::byte?

+
+
+

Even std::byte imposes a semantic opinion. POSIX uses void* for semantic neutrality—"raw memory, I move bytes without opining on contents."

+
+
+

But span<void> doesn’t compile—C++ can’t express type-agnostic buffer abstraction with span.

+
+
+

Capy provides const_buffer and mutable_buffer as semantically neutral buffer types. They have known layout compatible with OS structures (iovec, WSABUF) without imposing std::byte semantics.

+
+
+
+
+

Summary

+
+
+

The reflexive span<span<byte>> approach:

+
+
+
    +
  • +

    Forces allocation on every composition

    +
  • +
  • +

    Leads to overload proliferation

    +
  • +
  • +

    Loses the compositional power of generic programming

    +
  • +
+
+
+

The concept-driven approach:

+
+
+
    +
  • +

    Enables zero-allocation composition

    +
  • +
  • +

    Provides a single signature that accepts anything buffer-like

    +
  • +
  • +

    Follows proven STL design principles

    +
  • +
+
+
+

Continue to Buffer Types to learn about const_buffer and mutable_buffer.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5b.types.html b/preview/5.buffers/5b.types.html new file mode 100644 index 0000000..568afa9 --- /dev/null +++ b/preview/5.buffers/5b.types.html @@ -0,0 +1,657 @@ + + + + + + + + + + + + + + Buffer Types :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Buffer Types

+
+
+
+

This section introduces Capy’s fundamental buffer types: const_buffer and mutable_buffer.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Why Not std::byte?

+
+
+

std::byte imposes a semantic opinion. It says "this is raw bytes"—but that is itself an opinion about the data’s nature.

+
+
+

POSIX uses void* for buffers. This expresses semantic neutrality: "I move memory without opining on what it contains." The OS doesn’t care if the bytes represent text, integers, or compressed data—it moves them.

+
+
+

But std::span<void> doesn’t compile. C++ can’t express a type-agnostic buffer abstraction using span.

+
+
+

Capy provides const_buffer and mutable_buffer as semantically neutral buffer types with known layout.

+
+
+
+
+

const_buffer

+
+
+

const_buffer represents a contiguous region of read-only memory:

+
+
+
+
class const_buffer
+{
+public:
+    const_buffer() = default;
+    const_buffer(void const* data, std::size_t size) noexcept;
+    const_buffer(mutable_buffer const& b) noexcept;  // Implicit conversion
+
+    void const* data() const noexcept;
+    std::size_t size() const noexcept;
+
+    const_buffer& operator+=(std::size_t n) noexcept;  // Remove prefix
+};
+
+
+
+

Construction

+
+
+
// From pointer and size
+char data[] = "hello";
+const_buffer buf(data, 5);
+
+// From mutable_buffer (implicit)
+mutable_buffer mbuf(data, 5);
+const_buffer cbuf = mbuf;  // OK: mutable -> const
+
+
+
+
+

Accessors

+
+
+
const_buffer buf(data, 5);
+
+void const* ptr = buf.data();  // Pointer to first byte
+std::size_t len = buf.size();  // Number of bytes
+
+
+
+
+

Prefix Removal

+
+

The += operator removes bytes from the front of the buffer:

+
+
+
+
const_buffer buf(data, 10);
+
+buf += 3;  // Remove first 3 bytes
+// buf.data() now points 3 bytes later
+// buf.size() is now 7
+
+
+
+

This is useful when processing a buffer incrementally.

+
+
+
+
+
+

mutable_buffer

+
+
+

mutable_buffer represents a contiguous region of writable memory:

+
+
+
+
class mutable_buffer
+{
+public:
+    mutable_buffer() = default;
+    mutable_buffer(void* data, std::size_t size) noexcept;
+
+    void* data() const noexcept;
+    std::size_t size() const noexcept;
+
+    mutable_buffer& operator+=(std::size_t n) noexcept;
+};
+
+
+
+

The interface mirrors const_buffer, but data() returns non-const void*.

+
+
+

Conversion

+
+

mutable_buffer implicitly converts to const_buffer:

+
+
+
+
void process(const_buffer buf);
+
+mutable_buffer mbuf(data, size);
+process(mbuf);  // OK: implicit conversion
+
+
+
+

The reverse is not allowed—you cannot implicitly convert const_buffer to mutable_buffer.

+
+
+
+
+
+

make_buffer

+
+
+

The make_buffer function creates buffers from various sources:

+
+
+
+
#include <boost/capy/buffers/make_buffer.hpp>
+
+// From pointer and size
+auto buf = make_buffer(ptr, size);
+
+// From C array
+char arr[10];
+auto buf = make_buffer(arr);
+
+// From std::array
+std::array<char, 10> arr;
+auto buf = make_buffer(arr);
+
+// From std::vector
+std::vector<char> vec(100);
+auto buf = make_buffer(vec);
+
+// From std::string
+std::string str = "hello";
+auto buf = make_buffer(str);
+
+// From std::string_view
+std::string_view sv = "hello";
+auto buf = make_buffer(sv);
+
+
+
+

The returned buffer type depends on constness:

+
+
+
    +
  • +

    Non-const containers → mutable_buffer

    +
  • +
  • +

    Const containers, string_viewconst_buffer

    +
  • +
+
+
+
+
+

Layout Compatibility

+
+
+

const_buffer and mutable_buffer have the same memory layout as OS buffer structures:

+
+
+
    +
  • +

    POSIX: struct iovec { void* iov_base; size_t iov_len; }

    +
  • +
  • +

    Windows: struct WSABUF { ULONG len; CHAR* buf; } (note: different order)

    +
  • +
+
+
+

This means conversion to OS structures is efficient—often just a reinterpret_cast for arrays of buffers.

+
+
+
+
+

Single Buffers as Sequences

+
+
+

A single buffer is a degenerate sequence—a sequence with one element. The ConstBufferSequence and MutableBufferSequence concepts recognize this:

+
+
+
+
template<ConstBufferSequence Buffers>
+void write_data(Buffers const& buffers);
+
+// All of these work:
+write_data(make_buffer("hello"));         // Single buffer
+write_data(std::array{buf1, buf2, buf3}); // Multiple buffers
+write_data(my_composite);                  // Custom sequence
+
+
+
+

The library provides begin() and end() functions that work uniformly:

+
+
+
+
const_buffer single;
+auto it = begin(single);  // Returns pointer to single
+auto e = end(single);     // Returns pointer past single
+
+std::array<const_buffer, 3> multi;
+auto it = begin(multi);   // Returns multi.begin()
+auto e = end(multi);      // Returns multi.end()
+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/buffers.hpp>

Core buffer types and concepts

<boost/capy/buffers/make_buffer.hpp>

Buffer creation utilities

+
+

You have now learned about const_buffer and mutable_buffer. Continue to Buffer Sequences to understand how these types compose into sequences.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5c.sequences.html b/preview/5.buffers/5c.sequences.html new file mode 100644 index 0000000..8dfe2a2 --- /dev/null +++ b/preview/5.buffers/5c.sequences.html @@ -0,0 +1,650 @@ + + + + + + + + + + + + + + Buffer Sequences :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Buffer Sequences

+
+
+
+

This section explains buffer sequences—the concept that enables zero-allocation composition of buffers.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Buffer Types

    +
  • +
  • +

    Understanding of const_buffer and mutable_buffer

    +
  • +
+
+
+
+
+

What Is a Buffer Sequence?

+
+
+

A buffer sequence is any type that can produce an iteration of buffers. Formally:

+
+
+
    +
  • +

    A single buffer (like const_buffer) is a sequence of one element

    +
  • +
  • +

    A range of buffers (like vector<const_buffer>) is a multi-element sequence

    +
  • +
  • +

    Any bidirectional range with buffer-convertible values qualifies

    +
  • +
+
+
+
+
+

The Concepts

+
+
+

ConstBufferSequence

+
+
+
template<typename T>
+concept ConstBufferSequence =
+    std::is_convertible_v<T, const_buffer> || (
+        std::ranges::bidirectional_range<T> &&
+        std::is_convertible_v<std::ranges::range_value_t<T>, const_buffer>);
+
+
+
+

A type satisfies ConstBufferSequence if:

+
+
+
    +
  • +

    It converts to const_buffer directly (single buffer), OR

    +
  • +
  • +

    It is a bidirectional range whose elements convert to const_buffer

    +
  • +
+
+
+
+

MutableBufferSequence

+
+
+
template<typename T>
+concept MutableBufferSequence =
+    std::is_convertible_v<T, mutable_buffer> || (
+        std::ranges::bidirectional_range<T> &&
+        std::is_convertible_v<std::ranges::range_value_t<T>, mutable_buffer>);
+
+
+
+

Same pattern, but for mutable_buffer.

+
+
+
+
+
+

Satisfying the Concepts

+
+
+

Many common types satisfy these concepts:

+
+
+
+
// Single buffers
+const_buffer cb;                    // ConstBufferSequence
+mutable_buffer mb;                  // MutableBufferSequence (and ConstBufferSequence)
+
+// Standard containers of buffers
+std::vector<const_buffer> v;        // ConstBufferSequence
+std::array<mutable_buffer, 3> a;    // MutableBufferSequence
+
+// String types (convert to single buffer)
+std::string str;                    // ConstBufferSequence (via make_buffer)
+std::string_view sv;                // ConstBufferSequence
+
+
+
+
+
+

Heterogeneous Composition

+
+
+

Because the concept accepts anything convertible to buffer, you can mix types:

+
+
+
+
template<ConstBufferSequence Buffers>
+void send(Buffers const& bufs);
+
+// All of these work:
+send(make_buffer("Hello"));                    // string literal
+send(std::string_view{"Hello"});               // string_view
+send(std::array{buf1, buf2});                  // array of buffers
+send(my_custom_buffer_sequence);               // custom type
+
+
+
+
+
+

Iterating Buffer Sequences

+
+
+

Use begin() and end() from <boost/capy/buffers.hpp>:

+
+
+
+
template<ConstBufferSequence Buffers>
+void process(Buffers const& bufs)
+{
+    for (auto it = begin(bufs); it != end(bufs); ++it)
+    {
+        const_buffer buf = *it;
+        // Process buf.data(), buf.size()
+    }
+}
+
+
+
+

These functions handle both single buffers (returning pointer-to-self) and ranges (returning standard iterators).

+
+
+
+
+

consuming_buffers

+
+
+

When transferring data incrementally, consuming_buffers tracks progress:

+
+
+
+
#include <boost/capy/buffers/consuming_buffers.hpp>
+
+template<MutableBufferSequence Buffers>
+task<std::size_t> read_all(Stream& stream, Buffers buffers)
+{
+    consuming_buffers<Buffers> remaining(buffers);
+    std::size_t total = 0;
+
+    while (buffer_size(remaining) > 0)
+    {
+        auto [ec, n] = co_await stream.read_some(remaining);
+        if (ec.failed())
+            break;
+        remaining.consume(n);
+        total += n;
+    }
+
+    co_return total;
+}
+
+
+
+

consuming_buffers wraps a buffer sequence and provides:

+
+
+
    +
  • +

    consume(n) — Mark n bytes as consumed (remove from front)

    +
  • +
  • +

    Iteration over unconsumed buffers

    +
  • +
  • +

    buffer_size() of remaining bytes

    +
  • +
+
+
+
+
+

Zero-Allocation Composition

+
+
+

The cat() function composes buffer sequences without allocation:

+
+
+
+
auto headers = std::array{header_buf1, header_buf2};
+auto body = body_buffer;
+
+auto combined = cat(headers, body);  // No allocation
+
+// combined satisfies ConstBufferSequence
+// Iteration yields: header_buf1, header_buf2, body_buffer
+
+
+
+

The returned object stores references (or small copies for single buffers) and iterates through the composed sequence on demand.

+
+
+
+
+

Why Bidirectional?

+
+
+

The concepts require bidirectional ranges (not just forward ranges) for two reasons:

+
+
+
    +
  1. +

    Some algorithms traverse buffers backwards

    +
  2. +
  3. +

    consuming_buffers needs to adjust the first buffer’s start position

    +
  4. +
+
+
+

If your custom buffer sequence only provides forward iteration, wrap it in a type that provides bidirectional access.

+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/buffers.hpp>

Concepts and iteration functions

<boost/capy/buffers/consuming_buffers.hpp>

Incremental consumption wrapper

+
+

You have now learned how buffer sequences enable zero-allocation composition. Continue to System I/O Integration to see how buffer sequences interface with operating system I/O.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5d.system-io.html b/preview/5.buffers/5d.system-io.html new file mode 100644 index 0000000..9713e36 --- /dev/null +++ b/preview/5.buffers/5d.system-io.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + System I/O Integration :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

System I/O Integration

+
+
+
+

This section explains how buffer sequences interface with operating system I/O operations.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Buffer Sequences

    +
  • +
  • +

    Understanding of buffer sequence concepts

    +
  • +
+
+
+
+
+

The Virtual Boundary

+
+
+

User-facing APIs use concepts for composition flexibility. But at type-erasure boundaries—where virtual functions are needed—concrete types are required.

+
+
+

Capy’s design:

+
+
+
    +
  • +

    User-facing API — Accepts ConstBufferSequence or MutableBufferSequence concepts

    +
  • +
  • +

    Internal boundary — Converts to concrete arrays for virtual dispatch

    +
  • +
  • +

    OS interface — Translates to platform-specific structures

    +
  • +
+
+
+

The library handles all conversions automatically.

+
+
+
+
+

Platform Buffer Structures

+
+
+

POSIX: iovec

+
+
+
struct iovec {
+    void*  iov_base;  // Pointer to data
+    size_t iov_len;   // Length of data
+};
+
+
+
+

Used with readv(), writev(), recvmsg(), sendmsg().

+
+
+
+

Windows: WSABUF

+
+
+
typedef struct _WSABUF {
+    ULONG  len;  // Length (note: first!)
+    CHAR*  buf;  // Pointer
+} WSABUF;
+
+
+
+

Used with WSARecv(), WSASend().

+
+
+

Note the different member order—Capy handles this platform difference internally.

+
+
+
+
+
+

Translation Process

+
+
+

When you call an I/O function with a buffer sequence:

+
+
+
+
template<ConstBufferSequence Buffers>
+io_result<std::size_t> write_some(Buffers const& buffers);
+
+
+
+

Internally, Capy:

+
+
+
    +
  1. +

    Counts the number of buffers in the sequence

    +
  2. +
  3. +

    Allocates space for platform buffer structures (on stack for small sequences)

    +
  4. +
  5. +

    Copies buffer descriptors (pointer/size pairs) to platform structures

    +
  6. +
  7. +

    Calls the OS function with the platform array

    +
  8. +
  9. +

    Returns the result

    +
  10. +
+
+
+
+
+

Stack-Based Conversion

+
+
+

For common cases (small numbers of buffers), conversion happens on the stack:

+
+
+
+
// Pseudocode of internal implementation
+template<ConstBufferSequence Buffers>
+auto platform_write(Buffers const& buffers)
+{
+    std::size_t count = buffer_length(buffers);
+
+    if (count <= 8)  // Small buffer optimization
+    {
+        iovec iovecs[8];
+        fill_iovecs(iovecs, buffers, count);
+        return writev(fd, iovecs, count);
+    }
+    else  // Heap fallback
+    {
+        std::vector<iovec> iovecs(count);
+        fill_iovecs(iovecs.data(), buffers, count);
+        return writev(fd, iovecs.data(), count);
+    }
+}
+
+
+
+

Most real-world code uses fewer than 8 buffers, so heap allocation is rarely needed.

+
+
+
+
+

Scatter/Gather Benefits

+
+
+

Using vectored I/O provides:

+
+
+

Fewer System Calls

+
+

Without scatter/gather:

+
+
+
+
write(fd, header, header_len);  // syscall 1
+write(fd, body, body_len);      // syscall 2
+
+
+
+

With scatter/gather:

+
+
+
+
iovec iov[2] = {{header, header_len}, {body, body_len}};
+writev(fd, iov, 2);  // single syscall
+
+
+
+
+

Zero-Copy Transmission

+
+

Data doesn’t need to be copied into a single contiguous buffer. The OS reads directly from each buffer in sequence.

+
+
+
+

Atomic Operations

+
+

The vectored write is atomic at the file offset level—other processes see either none or all of the data.

+
+
+
+
+
+

Registered Buffers

+
+
+

Advanced platforms offer registered buffer optimizations:

+
+
+

io_uring (Linux 5.1+)

+
+

Buffers can be pre-registered with the kernel, eliminating per-operation address translation:

+
+
+
+
// Registration (done once)
+io_uring_register_buffers(ring, buffers, count);
+
+// Use (fast path - no translation)
+io_uring_prep_write_fixed(sqe, fd, buf, len, offset, buf_index);
+
+
+
+
+

IOCP (Windows)

+
+

Similar optimization with pre-registered memory regions for zero-copy I/O.

+
+
+

Capy’s Corosio library exposes these optimizations where available.

+
+
+
+
+
+

Writing Efficient Code

+
+
+

Minimize Buffer Count

+
+

Fewer buffers means less translation overhead:

+
+
+
+
// Prefer: single buffer when possible
+auto buf = assemble_message();  // Build in one buffer
+write(stream, buf);
+
+// Avoid: many tiny buffers
+std::array<const_buffer, 100> tiny_bufs;
+write(stream, tiny_bufs);  // 100-element translation
+
+
+
+
+

Reuse Buffer Structures

+
+

For repeated I/O with the same structure, consider caching the platform buffer array:

+
+
+
+
// Build once, use many times
+struct message_buffers
+{
+    std::array<iovec, 3> iovecs;
+
+    void set_header(void const* p, std::size_t n);
+    void set_body(void const* p, std::size_t n);
+    void set_footer(void const* p, std::size_t n);
+};
+
+
+
+
+

Profile Before Optimizing

+
+

Buffer translation is rarely the bottleneck. Focus on:

+
+
+
    +
  • +

    Network latency

    +
  • +
  • +

    Disk I/O time

    +
  • +
  • +

    Data processing logic

    +
  • +
+
+
+

Not buffer descriptor copying.

+
+
+
+
+
+

Reference

+
+
+

The buffer sequence concepts and translation utilities are in:

+
+
+
+
#include <boost/capy/buffers.hpp>
+
+
+
+

OS-specific I/O is handled by Corosio, which builds on Capy’s buffer model.

+
+
+

You have now learned how buffer sequences integrate with operating system I/O. Continue to Buffer Algorithms to learn about measuring and copying buffers.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5e.algorithms.html b/preview/5.buffers/5e.algorithms.html new file mode 100644 index 0000000..169b631 --- /dev/null +++ b/preview/5.buffers/5e.algorithms.html @@ -0,0 +1,723 @@ + + + + + + + + + + + + + + Buffer Algorithms :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Buffer Algorithms

+
+
+
+

This section covers algorithms for measuring and manipulating buffer sequences.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Buffer Sequences

    +
  • +
  • +

    Understanding of ConstBufferSequence and iteration

    +
  • +
+
+
+
+
+

Measuring Buffers

+
+
+

buffer_size

+
+

Returns the total number of bytes across all buffers in a sequence:

+
+
+
+
template<ConstBufferSequence CB>
+std::size_t buffer_size(CB const& buffers);
+
+
+
+

Example:

+
+
+
+
auto buf1 = make_buffer("hello");  // 5 bytes
+auto buf2 = make_buffer("world");  // 5 bytes
+auto combined = std::array{buf1, buf2};
+
+std::size_t total = buffer_size(combined);  // 10
+
+
+
+

Note: buffer_size returns the sum of bytes, not the count of buffers.

+
+
+
+

buffer_empty

+
+

Checks if a buffer sequence contains no data:

+
+
+
+
template<ConstBufferSequence CB>
+bool buffer_empty(CB const& buffers);
+
+
+
+

A buffer sequence is empty if:

+
+
+
    +
  • +

    It contains no buffers, OR

    +
  • +
  • +

    All buffers have size zero

    +
  • +
+
+
+
+
const_buffer empty_buf;
+buffer_empty(empty_buf);  // true
+
+const_buffer non_empty("data", 4);
+buffer_empty(non_empty);  // false
+
+
+
+
+

buffer_length

+
+

Returns the number of buffers in a sequence:

+
+
+
+
template<ConstBufferSequence CB>
+std::size_t buffer_length(CB const& buffers);
+
+
+
+

Example:

+
+
+
+
auto single = make_buffer("hello");
+buffer_length(single);  // 1
+
+auto arr = std::array{buf1, buf2, buf3};
+buffer_length(arr);  // 3
+
+
+
+

Note the distinction:

+
+
+
    +
  • +

    buffer_size — total bytes (data measurement)

    +
  • +
  • +

    buffer_length — number of buffers (sequence length)

    +
  • +
+
+
+
+
+
+

Copying Buffers

+
+
+

buffer_copy

+
+

Copies data from one buffer sequence to another:

+
+
+
+
template<MutableBufferSequence Target, ConstBufferSequence Source>
+std::size_t buffer_copy(Target const& target, Source const& source);
+
+template<MutableBufferSequence Target, ConstBufferSequence Source>
+std::size_t buffer_copy(Target const& target, Source const& source,
+                        std::size_t at_most);
+
+
+
+

Returns the number of bytes copied.

+
+
+

Example:

+
+
+
+
char source_data[] = "hello world";
+char dest_data[20];
+
+const_buffer src(source_data, 11);
+mutable_buffer dst(dest_data, 20);
+
+std::size_t copied = buffer_copy(dst, src);  // 11
+
+
+
+
+

Partial Copy with at_most

+
+

Limit the number of bytes copied:

+
+
+
+
std::size_t copied = buffer_copy(dst, src, 5);  // Copy at most 5 bytes
+
+
+
+

This is useful for implementing protocols with size limits.

+
+
+
+

Cross-Sequence Copy

+
+

buffer_copy handles sequences with different structure:

+
+
+
+
// Source: 3 buffers
+std::array<const_buffer, 3> src = {buf1, buf2, buf3};
+
+// Target: 2 buffers with different sizes
+std::array<mutable_buffer, 2> dst = {large_buf, small_buf};
+
+// Copies across buffer boundaries as needed
+std::size_t copied = buffer_copy(dst, src);
+
+
+
+

The algorithm fills target buffers sequentially, reading from source buffers as needed, handling cases where a single source buffer spans multiple target buffers or vice versa.

+
+
+
+
+
+

Real I/O Patterns

+
+
+

Read Loop

+
+
+
template<ReadStream Stream, MutableBufferSequence Buffers>
+task<std::size_t> read_full(Stream& stream, Buffers buffers)
+{
+    consuming_buffers<Buffers> remaining(buffers);
+    std::size_t total = 0;
+
+    while (buffer_size(remaining) > 0)
+    {
+        auto [ec, n] = co_await stream.read_some(remaining);
+        if (ec.failed())
+            co_return total;  // Return partial read on error
+
+        remaining.consume(n);
+        total += n;
+    }
+
+    co_return total;
+}
+
+
+
+
+

Write Loop

+
+
+
template<WriteStream Stream, ConstBufferSequence Buffers>
+task<std::size_t> write_full(Stream& stream, Buffers buffers)
+{
+    consuming_buffers<Buffers> remaining(buffers);
+    std::size_t total = 0;
+
+    while (buffer_size(remaining) > 0)
+    {
+        auto [ec, n] = co_await stream.write_some(remaining);
+        if (ec.failed())
+            co_return total;
+
+        remaining.consume(n);
+        total += n;
+    }
+
+    co_return total;
+}
+
+
+
+
+
+
+

Practical Benefits of Concept-Based Design

+
+
+

Zero-Copy I/O

+
+

Data never moves unnecessarily. The buffer sequence points to existing data, and the OS reads directly from those locations:

+
+
+
+
std::string header = build_header();
+std::vector<char> body = load_body();
+
+// No copying—header and body are written directly
+co_await write(stream, cat(make_buffer(header), make_buffer(body)));
+
+
+
+
+

Scatter/Gather Operations

+
+

Multiple buffers transfer in a single operation:

+
+
+
+
std::array buffers = {header_buf, separator_buf, body_buf, footer_buf};
+co_await write(stream, buffers);  // Single system call
+
+
+
+
+

Custom Allocators and Memory-Mapped Buffers

+
+

Any memory region can be a buffer:

+
+
+
+
// Memory-mapped file
+void* mapped = mmap(...);
+const_buffer file_buf(mapped, file_size);
+co_await write(socket, file_buf);  // Zero-copy network transmission
+
+
+
+
+

User-Defined Buffer Types

+
+

Create custom types that satisfy the concepts:

+
+
+
+
class chunked_buffer_sequence
+{
+    std::vector<std::vector<char>> chunks_;
+
+public:
+    auto begin() const { /* return iterator over chunks as buffers */ }
+    auto end() const { /* return end iterator */ }
+};
+// Satisfies ConstBufferSequence—works with all algorithms
+
+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/buffers.hpp>

Measurement algorithms (buffer_size, buffer_empty, buffer_length)

<boost/capy/buffers/buffer_copy.hpp>

Copy algorithm

+
+

You have now learned how to measure and copy buffer sequences. Continue to Dynamic Buffers to learn about growable buffer storage.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/5.buffers/5f.dynamic.html b/preview/5.buffers/5f.dynamic.html new file mode 100644 index 0000000..e703f47 --- /dev/null +++ b/preview/5.buffers/5f.dynamic.html @@ -0,0 +1,790 @@ + + + + + + + + + + + + + + Dynamic Buffers :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Dynamic Buffers

+
+
+
+

This section introduces dynamic buffers—growable storage that adapts to data flow between producers and consumers.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Buffer Algorithms

    +
  • +
  • +

    Understanding of buffer sequences and copying

    +
  • +
+
+
+
+
+

The Producer/Consumer Model

+
+
+

Dynamic buffers serve as intermediate storage between a producer (typically network I/O) and a consumer (your application code).

+
+
+

The flow:

+
+
+
    +
  1. +

    Producer writes data into the buffer

    +
  2. +
  3. +

    Buffer grows as needed to accommodate data

    +
  4. +
  5. +

    Consumer reads and processes data

    +
  6. +
  7. +

    Buffer releases consumed data

    +
  8. +
+
+
+

This model decouples production rate from consumption rate—the buffer absorbs variations.

+
+
+
+
+

The DynamicBuffer Concept

+
+
+
+
template<typename T>
+concept DynamicBuffer = requires(T& t, std::size_t n) {
+    // Producer side
+    { t.prepare(n) } -> MutableBufferSequence;
+    { t.commit(n) };
+
+    // Consumer side
+    { t.data() } -> ConstBufferSequence;
+    { t.consume(n) };
+
+    // Capacity
+    { t.size() } -> std::same_as<std::size_t>;
+    { t.max_size() } -> std::same_as<std::size_t>;
+    { t.capacity() } -> std::same_as<std::size_t>;
+};
+
+
+
+
+
+

Producer Interface

+
+
+

prepare(n)

+
+

Returns mutable buffer space for writing up to n bytes:

+
+
+
+
auto buffers = dynamic_buf.prepare(1024);  // Space for up to 1024 bytes
+
+
+
+

The returned space may be larger than requested. The data is not yet part of the readable sequence.

+
+
+
+

commit(n)

+
+

Marks n bytes of prepared space as written and readable:

+
+
+
+
// After writing data:
+dynamic_buf.commit(bytes_written);
+// Data is now visible via data()
+
+
+
+
+

Typical Producer Pattern

+
+
+
task<> read_into_buffer(Stream& stream, DynamicBuffer auto& buffer)
+{
+    // Prepare space
+    auto space = buffer.prepare(1024);
+
+    // Read into prepared space
+    auto [ec, n] = co_await stream.read_some(space);
+
+    if (!ec.failed())
+        buffer.commit(n);  // Make data readable
+}
+
+
+
+
+
+
+

Consumer Interface

+
+
+

data()

+
+

Returns the readable data as a const buffer sequence:

+
+
+
+
auto readable = dynamic_buf.data();
+// Process readable bytes
+
+
+
+
+

consume(n)

+
+

Removes n bytes from the front of readable data:

+
+
+
+
dynamic_buf.consume(processed_bytes);
+// Those bytes are no longer in data()
+
+
+
+
+

Typical Consumer Pattern

+
+
+
void process_buffer(DynamicBuffer auto& buffer)
+{
+    auto data = buffer.data();
+
+    while (buffer_size(data) >= message_header_size)
+    {
+        auto msg_size = parse_header(data);
+        if (buffer_size(data) < msg_size)
+            break;  // Need more data
+
+        process_message(data, msg_size);
+        buffer.consume(msg_size);
+        data = buffer.data();  // Refresh after consume
+    }
+}
+
+
+
+
+
+
+

Capacity Management

+
+
+
+
size()
+
+

Current number of readable bytes (the length of data()).

+
+
max_size()
+
+

Maximum allowed size. Attempts to grow beyond this throw or fail.

+
+
capacity()
+
+

Current allocated capacity. May be larger than size().

+
+
+
+
+
+
+

DynamicBufferParam

+
+
+

When passing dynamic buffers to coroutines, use DynamicBufferParam for safe parameter handling:

+
+
+
+
template<typename DB>
+concept DynamicBufferParam = DynamicBuffer<std::remove_reference_t<DB>>;
+
+template<DynamicBufferParam Buf>
+task<std::size_t> read_until(Stream& stream, Buf&& buffer, char delimiter);
+
+
+
+

This concept ensures proper handling of lvalues and rvalues, preventing dangling references across suspension points.

+
+
+
+
+

Provided Implementations

+
+
+

flat_dynamic_buffer

+
+

Linear storage with single-buffer sequences:

+
+
+
+
#include <boost/capy/buffers/flat_dynamic_buffer.hpp>
+
+flat_dynamic_buffer buffer;
+buffer.prepare(1024);
+// ... write data ...
+buffer.commit(n);
+
+// data() returns a single const_buffer
+
+
+
+

Advantages:

+
+
+
    +
  • +

    Contiguous memory—good for parsing that needs contiguous data

    +
  • +
  • +

    Cache-friendly

    +
  • +
+
+
+

Disadvantages:

+
+
+
    +
  • +

    May require copying when buffer wraps or grows

    +
  • +
+
+
+
+

circular_dynamic_buffer

+
+

Ring buffer implementation:

+
+
+
+
#include <boost/capy/buffers/circular_dynamic_buffer.hpp>
+
+circular_dynamic_buffer<1024> buffer;  // Fixed capacity
+
+
+
+

Advantages:

+
+
+
    +
  • +

    No copying on wrap—head/tail pointers move

    +
  • +
  • +

    Fixed memory footprint

    +
  • +
+
+
+

Disadvantages:

+
+
+
    +
  • +

    data() may return two buffers (wrapped around end)

    +
  • +
  • +

    Fixed capacity

    +
  • +
+
+
+
+

vector_dynamic_buffer

+
+

Backed by std::vector<char>:

+
+
+
+
#include <boost/capy/buffers/vector_dynamic_buffer.hpp>
+
+std::vector<char> storage;
+vector_dynamic_buffer buffer(storage);
+
+
+
+

Adapts an existing vector for use as a dynamic buffer.

+
+
+
+

string_dynamic_buffer

+
+

Backed by std::string:

+
+
+
+
#include <boost/capy/buffers/string_dynamic_buffer.hpp>
+
+std::string storage;
+string_dynamic_buffer buffer(storage);
+
+
+
+

Useful when you want the final data as a string.

+
+
+
+
+
+

Example: Line-Based Protocol

+
+
+
+
task<std::string> read_line(Stream& stream)
+{
+    flat_dynamic_buffer buffer;
+
+    while (true)
+    {
+        // Prepare space and read
+        auto space = buffer.prepare(256);
+        auto [ec, n] = co_await stream.read_some(space);
+        if (ec.failed())
+            throw std::system_error(ec);
+        buffer.commit(n);
+
+        // Search for newline in readable data
+        auto data = buffer.data();
+        std::string_view sv(
+            static_cast<char const*>(data.data()), data.size());
+
+        auto pos = sv.find('\n');
+        if (pos != std::string_view::npos)
+        {
+            std::string line(sv.substr(0, pos));
+            buffer.consume(pos + 1);  // Include newline
+            co_return line;
+        }
+    }
+}
+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/concept/dynamic_buffer.hpp>

DynamicBuffer concept definition

<boost/capy/buffers/flat_dynamic_buffer.hpp>

Linear dynamic buffer

<boost/capy/buffers/circular_dynamic_buffer.hpp>

Ring buffer implementation

<boost/capy/buffers/vector_dynamic_buffer.hpp>

Vector-backed adapter

<boost/capy/buffers/string_dynamic_buffer.hpp>

String-backed adapter

+
+

You have now learned about dynamic buffers for producer/consumer patterns. This completes the Buffer Sequences section. Continue to Stream Concepts to learn about Capy’s stream abstractions.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6.intro.html b/preview/6.streams/6.intro.html new file mode 100644 index 0000000..19a94dc --- /dev/null +++ b/preview/6.streams/6.intro.html @@ -0,0 +1,389 @@ + + + + + + + + + + + + + + Stream Concepts :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Stream Concepts

+
+

Data flows. It arrives from a network socket in unpredictable chunks. It leaves through a file descriptor as fast as the disk allows. It passes through encryption, compression, and framing layers—​each transforming it before handing it off to the next. Modeling this flow well is one of the most important things an I/O library can do.

+
+
+

Capy organizes data flow around six concepts, arranged in three complementary pairs. The design reflects a truth about I/O that most libraries gloss over: partial operations and complete operations are fundamentally different things, and conflating them leads to bugs.

+
+
+

A socket might give you 47 bytes when you asked for 1024. That is not an error—​it is the nature of the hardware. Some code needs to handle those 47 bytes immediately and ask for more. Other code needs exactly 1024 bytes and should not return until it has them (or an error occurs). These are different operations with different contracts, and Capy gives them different names: streams for partial I/O, and sources and sinks for complete I/O.

+
+
+

On top of this, Capy adds buffer sources and buffer sinks--concepts that work with dynamic buffers, enabling protocol parsers and message builders to grow their storage as needed without manual bookkeeping.

+
+
+

This section introduces the concepts that form Capy’s vocabulary for data flow. You will learn the distinction between partial and complete I/O, how the concept pairs relate to each other, and how transfer algorithms and physical isolation let you write I/O logic that is composable, testable, and independent of any particular transport. Once you understand these concepts, every I/O operation in the library will feel familiar.

+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6a.overview.html b/preview/6.streams/6a.overview.html new file mode 100644 index 0000000..266961a --- /dev/null +++ b/preview/6.streams/6a.overview.html @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + Stream Concepts Overview :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Stream Concepts Overview

+
+
+
+

This section introduces Capy’s stream concepts—the abstractions that enable data to flow through your programs.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Buffer Sequences

    +
  • +
  • +

    Understanding of buffer sequences and the DynamicBuffer concept

    +
  • +
+
+
+
+
+

Six Concepts for Data Flow

+
+
+

Capy defines six concepts for I/O operations, organized in three pairs:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConceptDirectionDescription

ReadStream

Read

Partial reads—returns whatever is available

WriteStream

Write

Partial writes—writes as much as possible

ReadSource

Read

Complete reads—fills buffer or signals EOF

WriteSink

Write

Complete writes with explicit EOF signaling

BufferSource

Read

Callee-owns-buffers read pattern

BufferSink

Write

Callee-owns-buffers write pattern

+
+
+
+

Streams vs Sources/Sinks

+
+
+

Streams: Partial I/O

+
+

Stream operations transfer some data and return. They do not guarantee a specific amount:

+
+
+
+
// ReadStream: may return fewer bytes than buffer can hold
+auto [ec, n] = co_await stream.read_some(buffer);
+// n might be 1, might be 1000, might be buffer_size(buffer)
+
+// WriteStream: may write fewer bytes than provided
+auto [ec, n] = co_await stream.write_some(buffers);
+// n might be less than buffer_size(buffers)
+
+
+
+

This matches raw OS behavior—syscalls return when data is available, not when buffers are full.

+
+
+
+

Sources/Sinks: Complete I/O

+
+

Source/sink operations complete fully or signal completion:

+
+
+
+
// ReadSource: fills buffer completely, or returns EOF/error with partial
+auto [ec, n] = co_await source.read(buffer);
+// n == buffer_size(buffer), or ec indicates why not
+
+// WriteSink: writes all data, with explicit EOF
+co_await sink.write_eof(buffers);  // atomic write + EOF signal
+
+
+
+

These are higher-level abstractions built on streams.

+
+
+
+
+
+

Buffer Sources/Sinks: Callee-Owns-Buffers

+
+
+

The third pair inverts buffer ownership:

+
+
+
    +
  • +

    With streams/sources/sinks, the caller provides buffers

    +
  • +
  • +

    With buffer sources/sinks, the callee provides buffers

    +
  • +
+
+
+
+
// BufferSource: callee provides read-only buffers
+const_buffer bufs[8];
+auto [ec, count] = co_await source.pull(bufs, 8);
+// bufs[0..count-1] now point to source's internal data
+
+// BufferSink: callee provides writable buffers
+mutable_buffer bufs[8];
+std::size_t count = sink.prepare(bufs, 8);
+// Write into bufs[0..count-1], then commit
+co_await sink.commit(bytes_written);
+
+
+
+

This pattern enables zero-copy I/O—data never moves through intermediate buffers.

+
+
+
+
+

Type-Erasing Wrappers

+
+
+

Each concept has a corresponding type-erasing wrapper:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConceptWrapper

ReadStream

any_read_stream

WriteStream

any_write_stream

(Both)

any_stream

ReadSource

any_read_source

WriteSink

any_write_sink

BufferSource

any_buffer_source

BufferSink

any_buffer_sink

+
+

These wrappers enable:

+
+
+
    +
  • +

    APIs independent of concrete transport

    +
  • +
  • +

    Compilation firewalls (fast incremental builds)

    +
  • +
  • +

    Runtime polymorphism without virtual inheritance in user code

    +
  • +
+
+
+
+
+

Choosing the Right Abstraction

+
+
+

Use Streams When:

+
+
    +
  • +

    You need raw, unbuffered I/O

    +
  • +
  • +

    You’re implementing a protocol that processes data incrementally

    +
  • +
  • +

    Performance is critical and you want minimal abstraction

    +
  • +
+
+
+
+

Use Sources/Sinks When:

+
+
    +
  • +

    You need complete data units (messages, records, frames)

    +
  • +
  • +

    EOF signaling is part of your protocol

    +
  • +
  • +

    You’re composing transformations (compression, encryption)

    +
  • +
+
+
+
+

Use Buffer Sources/Sinks When:

+
+
    +
  • +

    Zero-copy is essential

    +
  • +
  • +

    The source/sink owns the memory (memory-mapped files, hardware buffers)

    +
  • +
  • +

    You’re implementing a processing pipeline

    +
  • +
+
+
+
+
+
+

The Value Proposition

+
+
+

Type-erased wrappers let you write transport-agnostic code:

+
+
+
+
// This function works with any stream implementation
+task<> echo(any_stream& stream)
+{
+    char buf[1024];
+    for (;;)
+    {
+        auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+        if (ec)
+            co_return;
+
+        auto [wec, wn] = co_await write(stream, const_buffer(buf, n));
+        if (wec)
+            co_return;
+    }
+}
+
+
+
+

The caller decides the concrete implementation:

+
+
+
+
// Works with Corosio TCP sockets
+any_stream s1{tcp_socket};
+echo(s1);
+
+// Works with TLS streams
+any_stream s2{tls_stream};
+echo(s2);
+
+// Works with test mocks
+any_stream s3{test::stream{}};
+echo(s3);
+
+
+
+

Same code, different transports—compile once, link anywhere.

+
+
+

Continue to Streams (Partial I/O) to learn the ReadStream and WriteStream concepts in detail.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6b.streams.html b/preview/6.streams/6b.streams.html new file mode 100644 index 0000000..e80a5ea --- /dev/null +++ b/preview/6.streams/6b.streams.html @@ -0,0 +1,708 @@ + + + + + + + + + + + + + + Streams (Partial I/O) :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Streams (Partial I/O)

+
+
+
+

This section explains the ReadStream and WriteStream concepts for partial I/O operations.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

ReadStream

+
+
+

A type satisfies ReadStream if it provides partial read operations via read_some:

+
+
+
+
template<typename T>
+concept ReadStream =
+    requires(T& stream, mutable_buffer_archetype buffers) {
+        { stream.read_some(buffers) } -> IoAwaitable;
+    };
+
+
+
+

read_some Semantics

+
+
+
template<MutableBufferSequence Buffers>
+IoAwaitable auto read_some(Buffers buffers);
+
+
+
+

Returns an awaitable yielding (error_code, std::size_t):

+
+
+
    +
  • +

    On success: !ec, and n >= 1 bytes were read

    +
  • +
  • +

    On error: ec, and n == 0

    +
  • +
  • +

    On EOF: ec == cond::eof, and n == 0

    +
  • +
+
+
+

If buffer_empty(buffers) is true, completes immediately with n == 0 and no error.

+
+
+
+

Partial Transfer

+
+

read_some may return fewer bytes than the buffer can hold:

+
+
+
+
char buf[1024];
+auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+// n might be 1, might be 500, might be 1024
+// The only guarantee: if !ec && n > 0
+
+
+
+

This matches underlying OS behavior—reads return when some data is available.

+
+
+
+

Example

+
+
+
template<ReadStream Stream>
+task<> dump_stream(Stream& stream)
+{
+    char buf[256];
+
+    for (;;)
+    {
+        auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+
+        if (ec == cond::eof)
+            break;  // End of stream
+
+        if (ec)
+            throw std::system_error(ec);
+
+        std::cout.write(buf, n);
+    }
+}
+
+
+
+
+
+
+

WriteStream

+
+
+

A type satisfies WriteStream if it provides partial write operations via write_some:

+
+
+
+
template<typename T>
+concept WriteStream =
+    requires(T& stream, const_buffer_archetype buffers) {
+        { stream.write_some(buffers) } -> IoAwaitable;
+    };
+
+
+
+

write_some Semantics

+
+
+
template<ConstBufferSequence Buffers>
+IoAwaitable auto write_some(Buffers buffers);
+
+
+
+

Returns an awaitable yielding (error_code, std::size_t):

+
+
+
    +
  • +

    On success: !ec, and n >= 1 bytes were written

    +
  • +
  • +

    On error: ec, and n == 0

    +
  • +
+
+
+

If buffer_empty(buffers) is true, completes immediately with n == 0 and no error.

+
+
+
+

Partial Transfer

+
+

write_some may write fewer bytes than provided:

+
+
+
+
auto [ec, n] = co_await stream.write_some(make_buffer(large_data));
+// n might be less than large_data.size()
+
+
+
+

To write all data, loop until complete (or use the write() composed operation).

+
+
+
+
+
+

Type-Erasing Wrappers

+
+
+

any_read_stream

+
+

Wraps any ReadStream in a type-erased container:

+
+
+
+
#include <boost/capy/io/any_read_stream.hpp>
+
+template<ReadStream S>
+any_read_stream(S& stream);
+
+
+
+

The wrapped stream is referenced—the original must outlive the wrapper.

+
+
+
+

any_write_stream

+
+

Wraps any WriteStream:

+
+
+
+
#include <boost/capy/io/any_write_stream.hpp>
+
+template<WriteStream S>
+any_write_stream(S& stream);
+
+
+
+
+

any_stream

+
+

Wraps bidirectional streams (both ReadStream and WriteStream):

+
+
+
+
#include <boost/capy/io/any_stream.hpp>
+
+template<ReadStream S>
+    requires WriteStream<S>
+any_stream(S& stream);
+
+
+
+
+

Wrapper Characteristics

+
+

All wrappers share these properties:

+
+
+
    +
  • +

    Reference semantics — Wrap existing objects without ownership

    +
  • +
  • +

    Preallocated coroutine frame — Zero steady-state allocation

    +
  • +
  • +

    Move-only — Non-copyable; moving transfers the cached frame

    +
  • +
  • +

    Lifetime requirement — Wrapped object must outlive wrapper

    +
  • +
+
+
+

Example usage:

+
+
+
+
void process_stream(any_stream& stream);
+
+tcp::socket socket;
+// ... connect socket ...
+
+any_stream wrapped{socket};  // Type erasure here
+process_stream(wrapped);      // process_stream doesn't know about tcp::socket
+
+
+
+
+
+
+

Example: Echo Server with any_stream

+
+
+
+
// echo.hpp - Header only declares the signature
+task<> handle_connection(any_stream& stream);
+
+// echo.cpp - Implementation in separate translation unit
+task<> handle_connection(any_stream& stream)
+{
+    char buf[1024];
+
+    for (;;)
+    {
+        // Read some data
+        auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+
+        if (ec == cond::eof)
+            co_return;  // Client closed connection
+
+        if (ec)
+            throw std::system_error(ec);
+
+        // Echo it back
+        auto [wec, wn] = co_await write(stream, const_buffer(buf, n));
+
+        if (wec)
+            throw std::system_error(wec);
+    }
+}
+
+
+
+

The implementation doesn’t know the concrete stream type. It compiles once and works with any transport.

+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/concept/read_stream.hpp>

ReadStream concept definition

<boost/capy/concept/write_stream.hpp>

WriteStream concept definition

<boost/capy/io/any_read_stream.hpp>

Type-erased read stream wrapper

<boost/capy/io/any_write_stream.hpp>

Type-erased write stream wrapper

<boost/capy/io/any_stream.hpp>

Type-erased bidirectional stream wrapper

+
+

You have now learned the stream concepts for partial I/O. Continue to Sources and Sinks to learn about complete I/O with EOF signaling.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6c.sources-sinks.html b/preview/6.streams/6c.sources-sinks.html new file mode 100644 index 0000000..bf6b693 --- /dev/null +++ b/preview/6.streams/6c.sources-sinks.html @@ -0,0 +1,721 @@ + + + + + + + + + + + + + + Sources and Sinks (Complete I/O) :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Sources and Sinks (Complete I/O)

+
+
+
+

This section explains the ReadSource and WriteSink concepts for complete I/O operations with EOF signaling.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Streams (Partial I/O)

    +
  • +
  • +

    Understanding of partial I/O with ReadStream and WriteStream

    +
  • +
+
+
+
+
+

ReadSource

+
+
+

A ReadSource provides complete read operations that fill buffers entirely or signal EOF:

+
+
+
+
template<typename T>
+concept ReadSource =
+    ReadStream<T> &&
+    requires(T& source, mutable_buffer_archetype buffers) {
+        { source.read(buffers) } -> IoAwaitable;
+    };
+
+
+
+

read Semantics

+
+
+
template<MutableBufferSequence Buffers>
+IoAwaitable auto read(Buffers buffers);
+
+
+
+

Returns an awaitable yielding (error_code, std::size_t):

+
+
+
    +
  • +

    On success: !ec, and n == buffer_size(buffers) (buffer completely filled)

    +
  • +
  • +

    On EOF: ec == cond::eof, and n is bytes read before EOF (partial read)

    +
  • +
  • +

    On error: ec, and n is bytes read before error

    +
  • +
+
+
+

The key difference from ReadStream: a successful read fills the buffer completely.

+
+
+
+

Use Cases

+
+
    +
  • +

    Reading fixed-size records

    +
  • +
  • +

    Reading message frames with known sizes

    +
  • +
  • +

    Filling buffers for batch processing

    +
  • +
+
+
+
+

Example

+
+
+
template<ReadSource Source>
+task<std::optional<message>> read_message(Source& source)
+{
+    // Read fixed-size header
+    message_header header;
+    auto [ec, n] = co_await source.read(
+        mutable_buffer(&header, sizeof(header)));
+
+    if (ec == cond::eof && n == 0)
+        co_return std::nullopt;  // Clean EOF
+
+    if (ec)
+        throw std::system_error(ec);
+
+    // Read variable-size body
+    std::vector<char> body(header.body_size);
+    auto [ec2, n2] = co_await source.read(make_buffer(body));
+
+    if (ec2)
+        throw std::system_error(ec2);
+
+    co_return message{header, std::move(body)};
+}
+
+
+
+
+
+
+

WriteSink

+
+
+

A WriteSink provides complete write operations with explicit EOF signaling:

+
+
+
+
template<typename T>
+concept WriteSink =
+    WriteStream<T> &&
+    requires(T& sink, const_buffer_archetype buffers) {
+        { sink.write(buffers) } -> IoAwaitable;
+        { sink.write_eof(buffers) } -> IoAwaitable;
+        { sink.write_eof() } -> IoAwaitable;
+    };
+
+
+
+

write Semantics

+
+
+
// Partial write (inherited from WriteStream)
+template<ConstBufferSequence Buffers>
+IoAwaitable auto write_some(Buffers buffers);
+
+// Complete write
+template<ConstBufferSequence Buffers>
+IoAwaitable auto write(Buffers buffers);
+
+// Atomic final write + EOF signal
+template<ConstBufferSequence Buffers>
+IoAwaitable auto write_eof(Buffers buffers);
+
+// Signal EOF without data
+IoAwaitable auto write_eof();
+
+
+
+

write consumes the entire buffer sequence before returning. write_eof(buffers) atomically writes the buffer sequence and signals end-of-stream in a single operation, enabling protocol-level optimizations (e.g., HTTP chunked encoding terminal, compression trailers).

+
+
+

After calling write_eof(buffers) or write_eof(), no further writes are permitted.

+
+
+
+

Use Cases

+
+
    +
  • +

    Writing complete messages

    +
  • +
  • +

    HTTP body transmission (content-length or chunked)

    +
  • +
  • +

    Protocol framing with explicit termination

    +
  • +
+
+
+
+

Example

+
+
+
template<WriteSink Sink>
+task<> send_response(Sink& sink, response const& resp)
+{
+    // Write headers
+    auto headers = format_headers(resp);
+    auto [ec, n] = co_await sink.write(make_buffer(headers));
+    if (ec)
+        co_return;
+
+    // Write body and signal EOF atomically
+    auto [ec2, n2] = co_await sink.write_eof(make_buffer(resp.body));
+    if (ec2)
+        co_return;
+}
+
+
+
+
+
+
+

Type-Erasing Wrappers

+
+
+

any_read_source

+
+
+
#include <boost/capy/io/any_read_source.hpp>
+
+template<ReadSource S>
+any_read_source(S& source);
+
+
+
+
+

any_write_sink

+
+
+
#include <boost/capy/io/any_write_sink.hpp>
+
+template<WriteSink S>
+any_write_sink(S& sink);
+
+
+
+
+
+
+

Example: HTTP Body Handler

+
+
+

The HTTP library uses any_write_sink for body transmission:

+
+
+
+
// HTTP response handler doesn't know the underlying transport
+task<> send_body(any_write_sink& body, std::string_view data)
+{
+    // Works whether body is:
+    // - Direct socket write (content-length)
+    // - Chunked encoding wrapper
+    // - Compressed stream
+    // - Test mock
+
+    co_await body.write_eof(make_buffer(data));
+}
+
+
+
+

The caller decides the concrete implementation:

+
+
+
+
// Content-length mode
+content_length_sink cl_sink(socket, data.size());
+any_write_sink body{cl_sink};
+send_body(body, data);
+
+// Chunked mode
+chunked_sink ch_sink(socket);
+any_write_sink body{ch_sink};
+send_body(body, data);
+
+
+
+

Same send_body function, different transfer encodings—the library handles the difference.

+
+
+
+
+

Streams vs Sources/Sinks

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectStreamsSources/Sinks

Transfer amount

Partial (whatever is available)

Complete (fill buffer or EOF)

EOF handling

Implicit (read returns 0)

Explicit (write_eof(), write_eof(buffers))

Use case

Raw I/O, incremental processing

Message-oriented protocols

Abstraction level

Lower (closer to OS)

Higher (application-friendly)

+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/concept/read_source.hpp>

ReadSource concept definition

<boost/capy/concept/write_sink.hpp>

WriteSink concept definition

<boost/capy/io/any_read_source.hpp>

Type-erased read source wrapper

<boost/capy/io/any_write_sink.hpp>

Type-erased write sink wrapper

+
+

You have now learned about sources and sinks for complete I/O. Continue to Buffer Sources and Sinks to learn about the callee-owns-buffers pattern.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6d.buffer-concepts.html b/preview/6.streams/6d.buffer-concepts.html new file mode 100644 index 0000000..acd38b0 --- /dev/null +++ b/preview/6.streams/6d.buffer-concepts.html @@ -0,0 +1,720 @@ + + + + + + + + + + + + + + Buffer Sources and Sinks :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Buffer Sources and Sinks

+
+
+
+

This section explains the BufferSource and BufferSink concepts for zero-copy I/O where the callee owns the buffers.

+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Sources and Sinks

    +
  • +
  • +

    Understanding of caller-owns-buffers patterns

    +
  • +
+
+
+
+
+

Callee-Owns-Buffers Pattern

+
+
+

With streams and sources/sinks, the caller provides buffers:

+
+
+
+
// Caller owns the buffer
+char my_buffer[1024];
+co_await stream.read_some(mutable_buffer(my_buffer));
+
+
+
+

Data flows: source → caller’s buffer → processing

+
+
+

With buffer sources/sinks, the callee provides buffers:

+
+
+
+
// Callee owns the buffers
+const_buffer bufs[8];
+auto [ec, count] = co_await source.pull(bufs, 8);
+// bufs now point into source's internal storage
+
+
+
+

Data flows: source’s internal buffer → processing (no copy!)

+
+
+
+
+

BufferSource

+
+
+

A BufferSource provides read-only buffers from its internal storage:

+
+
+
+
template<typename T>
+concept BufferSource =
+    requires(T& source, const_buffer* arr, std::size_t max_count) {
+        { source.pull(arr, max_count) } -> IoAwaitable;
+    };
+
+
+
+

pull Semantics

+
+
+
IoAwaitable auto pull(const_buffer* arr, std::size_t max_count);
+
+
+
+

Returns an awaitable yielding (error_code, std::size_t):

+
+
+
    +
  • +

    On success: !ec.failed(), fills arr[0..count-1] with buffer descriptors

    +
  • +
  • +

    On exhausted: count == 0 indicates no more data

    +
  • +
  • +

    On error: ec.failed()

    +
  • +
+
+
+

The buffers point into the source’s internal storage. You must consume all returned data before calling pull() again—the previous buffers become invalid.

+
+
+
+

Example

+
+
+
template<BufferSource Source>
+task<> process_source(Source& source)
+{
+    const_buffer bufs[8];
+
+    for (;;)
+    {
+        auto [ec, count] = co_await source.pull(bufs, 8);
+
+        if (ec.failed())
+            throw std::system_error(ec);
+
+        if (count == 0)
+            break;  // Source exhausted
+
+        // Process buffers (zero-copy!)
+        for (std::size_t i = 0; i < count; ++i)
+            process_data(bufs[i].data(), bufs[i].size());
+    }
+}
+
+
+
+
+
+
+

BufferSink

+
+
+

A BufferSink provides writable buffers for direct write access:

+
+
+
+
template<typename T>
+concept BufferSink =
+    requires(T& sink, mutable_buffer* arr, std::size_t max_count, std::size_t n) {
+        { sink.prepare(arr, max_count) } -> std::same_as<std::size_t>;
+        { sink.commit(n) } -> IoAwaitable;
+        { sink.commit(n, bool{}) } -> IoAwaitable;
+        { sink.commit_eof() } -> IoAwaitable;
+    };
+
+
+
+

prepare Semantics

+
+
+
std::size_t prepare(mutable_buffer* arr, std::size_t max_count);
+
+
+
+

Synchronous operation. Returns the number of buffers prepared (may be less than max_count). Fills arr[0..count-1] with writable buffer descriptors.

+
+
+
+

commit Semantics

+
+
+
IoAwaitable auto commit(std::size_t n);
+IoAwaitable auto commit(std::size_t n, bool eof);
+IoAwaitable auto commit_eof();
+
+
+
+

Finalizes n bytes of prepared data. The eof flag or commit_eof() signals end-of-stream.

+
+
+
+

Example

+
+
+
template<BufferSink Sink>
+task<> write_to_sink(Sink& sink, std::span<char const> data)
+{
+    std::size_t written = 0;
+
+    while (written < data.size())
+    {
+        mutable_buffer bufs[8];
+        std::size_t count = sink.prepare(bufs, 8);
+
+        if (count == 0)
+            throw std::runtime_error("sink full");
+
+        // Copy into sink's buffers
+        std::size_t copied = 0;
+        for (std::size_t i = 0; i < count && written < data.size(); ++i)
+        {
+            std::size_t chunk = (std::min)(
+                bufs[i].size(),
+                data.size() - written);
+            std::memcpy(bufs[i].data(), data.data() + written, chunk);
+            written += chunk;
+            copied += chunk;
+        }
+
+        bool eof = (written == data.size());
+        co_await sink.commit(copied, eof);
+    }
+}
+
+
+
+
+
+
+

Zero-Copy Benefits

+
+
+

Buffer sources/sinks enable true zero-copy I/O:

+
+
+

Memory-Mapped Files

+
+
+
class mmap_source : public BufferSource
+{
+    void* mapped_region_;
+    std::size_t size_;
+    std::size_t offset_ = 0;
+
+public:
+    io_result<std::size_t> pull(const_buffer* arr, std::size_t max_count)
+    {
+        if (offset_ >= size_)
+            co_return {error_code{}, 0};  // Exhausted
+
+        // Return pointer into mapped memory—no copy!
+        arr[0] = const_buffer(
+            static_cast<char*>(mapped_region_) + offset_,
+            size_ - offset_);
+        offset_ = size_;
+
+        co_return {error_code{}, 1};
+    }
+};
+
+
+
+
+

Hardware Buffers

+
+

DMA buffers, GPU memory, network card ring buffers—all can be exposed through BufferSource/BufferSink without intermediate copying.

+
+
+
+
+
+

Type-Erasing Wrappers

+
+
+

any_buffer_source

+
+
+
#include <boost/capy/io/any_buffer_source.hpp>
+
+template<BufferSource S>
+any_buffer_source(S& source);
+
+
+
+
+

any_buffer_sink

+
+
+
#include <boost/capy/io/any_buffer_sink.hpp>
+
+template<BufferSink S>
+any_buffer_sink(S& sink);
+
+
+
+
+
+
+

Example: Compression Pipeline

+
+
+
+
// Compressor provides compressed data via BufferSource
+// Decompressor consumes compressed data via BufferSink
+
+task<> decompress_stream(any_buffer_source& compressed, any_write_sink& output)
+{
+    const_buffer bufs[8];
+
+    for (;;)
+    {
+        auto [ec, count] = co_await compressed.pull(bufs, 8);
+        if (ec.failed())
+            throw std::system_error(ec);
+        if (count == 0)
+            break;
+
+        for (std::size_t i = 0; i < count; ++i)
+        {
+            auto decompressed = decompress_block(bufs[i]);
+            co_await output.write(make_buffer(decompressed));
+        }
+    }
+
+    co_await output.write_eof();
+}
+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/concept/buffer_source.hpp>

BufferSource concept definition

<boost/capy/concept/buffer_sink.hpp>

BufferSink concept definition

<boost/capy/io/any_buffer_source.hpp>

Type-erased buffer source wrapper

<boost/capy/io/any_buffer_sink.hpp>

Type-erased buffer sink wrapper

+
+

You have now learned about buffer sources and sinks for zero-copy I/O. Continue to Transfer Algorithms to learn about composed read/write operations.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6e.algorithms.html b/preview/6.streams/6e.algorithms.html new file mode 100644 index 0000000..16bde46 --- /dev/null +++ b/preview/6.streams/6e.algorithms.html @@ -0,0 +1,734 @@ + + + + + + + + + + + + + + Transfer Algorithms :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Transfer Algorithms

+
+
+
+

This section explains the composed read/write operations and transfer algorithms.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Composed Read/Write

+
+
+

The partial operations (read_some, write_some) often require looping. Capy provides composed operations that handle the loops for you.

+
+
+

read

+
+

Fills a buffer completely by looping read_some:

+
+
+
+
#include <boost/capy/read.hpp>
+
+template<ReadStream Stream, MutableBufferSequence Buffers>
+task<std::pair<error_code, std::size_t>>
+read(Stream& stream, Buffers const& buffers);
+
+
+
+

Keeps reading until:

+
+
+
    +
  • +

    Buffer is full (n == buffer_size(buffers))

    +
  • +
  • +

    EOF is reached (returns cond::eof with partial count)

    +
  • +
  • +

    Error occurs (returns error with partial count)

    +
  • +
+
+
+

Example:

+
+
+
+
char buf[1024];
+auto [ec, n] = co_await read(stream, mutable_buffer(buf));
+// n == 1024, or ec indicates why not
+
+
+
+
+

read with DynamicBuffer

+
+

Reads until EOF into a growable buffer:

+
+
+
+
template<ReadStream Stream, DynamicBuffer Buffer>
+task<std::pair<error_code, std::size_t>>
+read(Stream& stream, Buffer&& buffer);
+
+
+
+

Example:

+
+
+
+
flat_dynamic_buffer buf;
+auto [ec, n] = co_await read(stream, buf);
+// buf now contains all data until EOF
+
+
+
+
+

write

+
+

Writes all data by looping write_some:

+
+
+
+
#include <boost/capy/write.hpp>
+
+template<WriteStream Stream, ConstBufferSequence Buffers>
+task<std::pair<error_code, std::size_t>>
+write(Stream& stream, Buffers const& buffers);
+
+
+
+

Keeps writing until:

+
+
+
    +
  • +

    All data is written (n == buffer_size(buffers))

    +
  • +
  • +

    Error occurs (returns error with partial count)

    +
  • +
+
+
+

Example:

+
+
+
+
co_await write(stream, make_buffer("Hello, World!"));
+
+
+
+
+
+
+

Transfer Algorithms

+
+
+

Transfer algorithms move data between sources/sinks and streams.

+
+
+

push_to

+
+

Transfers data from a BufferSource to a destination:

+
+
+
+
#include <boost/capy/io/push_to.hpp>
+
+// To WriteSink (with EOF propagation)
+template<BufferSource Source, WriteSink Sink>
+task<std::pair<error_code, std::size_t>>
+push_to(Source& source, Sink& sink);
+
+// To WriteStream (streaming, no EOF)
+template<BufferSource Source, WriteStream Stream>
+task<std::pair<error_code, std::size_t>>
+push_to(Source& source, Stream& stream);
+
+
+
+

The source provides buffers via pull(). Data is pushed to the destination. Buffer ownership stays with the source—no intermediate copying when possible.

+
+
+

Example:

+
+
+
+
// Transfer file to network
+mmap_source file("large_file.bin");
+co_await push_to(file, socket);
+
+
+
+
+

pull_from

+
+

Transfers data from a source to a BufferSink:

+
+
+
+
#include <boost/capy/io/pull_from.hpp>
+
+// From ReadSource
+template<ReadSource Source, BufferSink Sink>
+task<std::pair<error_code, std::size_t>>
+pull_from(Source& source, Sink& sink);
+
+// From ReadStream (streaming)
+template<ReadStream Stream, BufferSink Sink>
+task<std::pair<error_code, std::size_t>>
+pull_from(Stream& stream, Sink& sink);
+
+
+
+

The sink provides writable buffers via prepare(). Data is pulled from the source directly into the sink’s buffers.

+
+
+

Example:

+
+
+
+
// Receive network data into compression buffer
+compression_sink compressor;
+co_await pull_from(socket, compressor);
+
+
+
+
+

Why No buffer-to-buffer?

+
+

There is no push_to(BufferSource, BufferSink) because it would require redundant copying. The source owns read-only buffers; the sink owns writable buffers. Transferring between them would need an intermediate copy, defeating the zero-copy purpose.

+
+
+

Instead, compose with an intermediate stage:

+
+
+
+
// Transform: BufferSource → processing → BufferSink
+task<> process_pipeline(any_buffer_source& source, any_buffer_sink& sink)
+{
+    const_buffer src_bufs[8];
+
+    while (true)
+    {
+        auto [ec, count] = co_await source.pull(src_bufs, 8);
+        if (count == 0)
+            break;
+
+        for (std::size_t i = 0; i < count; ++i)
+        {
+            auto processed = transform(src_bufs[i]);
+
+            // Write processed data to sink
+            mutable_buffer dst_bufs[8];
+            std::size_t dst_count = sink.prepare(dst_bufs, 8);
+
+            std::size_t copied = buffer_copy(
+                std::span(dst_bufs, dst_count),
+                make_buffer(processed));
+
+            co_await sink.commit(copied);
+        }
+    }
+
+    co_await sink.commit_eof();
+}
+
+
+
+
+
+
+

Naming Convention

+
+
+

The algorithm names reflect buffer ownership:

+
+ ++++ + + + + + + + + + + + + + + + + +
NameMeaning

push_to

Source provides buffers → push data to destination

pull_from

Sink provides buffers → pull data from source

+
+

The preposition indicates the direction of buffer provision, not data flow.

+
+
+
+
+

Error Handling

+
+
+

All transfer algorithms return (error_code, std::size_t):

+
+
+
    +
  • +

    error_code — Success, EOF, or error condition

    +
  • +
  • +

    std::size_t — Total bytes transferred before return

    +
  • +
+
+
+

On error, partial transfer may have occurred. The returned count indicates how much was transferred.

+
+
+

Example:

+
+
+
+
auto [ec, total] = co_await push_to(source, sink);
+
+if (ec == cond::eof)
+{
+    // Normal completion
+    std::cout << "Transferred " << total << " bytes\n";
+}
+else if (ec.failed())
+{
+    // Error occurred
+    std::cerr << "Error after " << total << " bytes: " << ec.message() << "\n";
+}
+
+
+
+
+
+

Reference

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderDescription

<boost/capy/read.hpp>

Composed read operations

<boost/capy/write.hpp>

Composed write operations

<boost/capy/io/push_to.hpp>

BufferSource → WriteSink/WriteStream transfer

<boost/capy/io/pull_from.hpp>

ReadSource/ReadStream → BufferSink transfer

+
+

You have now learned about transfer algorithms. Continue to Physical Isolation to learn how type erasure enables compilation firewalls.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/6.streams/6f.isolation.html b/preview/6.streams/6f.isolation.html new file mode 100644 index 0000000..0d12dda --- /dev/null +++ b/preview/6.streams/6f.isolation.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + + Physical Isolation :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Physical Isolation

+
+
+
+

This section explains how type-erased wrappers enable compilation firewalls and transport-independent APIs.

+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

The Compilation Firewall Pattern

+
+
+

C++ templates are powerful but have a cost: every instantiation compiles in every translation unit that uses it. Change a template, and everything that includes it recompiles.

+
+
+

Type-erased wrappers break this dependency:

+
+
+
+
// protocol.hpp - No template dependencies
+#pragma once
+#include <boost/capy/io/any_stream.hpp>
+#include <boost/capy/task.hpp>
+
+// Declaration only - no implementation details
+task<> handle_protocol(any_stream& stream);
+
+
+
+
+
// protocol.cpp - Implementation isolated here
+#include "protocol.hpp"
+#include <boost/capy/read.hpp>
+#include <boost/capy/write.hpp>
+
+task<> handle_protocol(any_stream& stream)
+{
+    char buf[1024];
+
+    for (;;)
+    {
+        auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+        if (ec.failed())
+            co_return;
+
+        // Process and respond...
+        co_await write(stream, make_buffer(response));
+    }
+}
+
+
+
+

Changes to protocol.cpp only recompile that file. The header is stable.

+
+
+
+
+

Build Time Benefits

+
+
+

Before (Templates Everywhere)

+
+
+
// Old approach: template propagates everywhere
+template<typename Stream>
+task<> handle_protocol(Stream& stream);
+
+// Every caller instantiates for their stream type
+// Changes force recompilation of all callers
+
+
+
+
+

After (Type Erasure at Boundary)

+
+
+
// New approach: concrete signature
+task<> handle_protocol(any_stream& stream);
+
+// Implementation compiles once
+// Callers only depend on the signature
+
+
+
+
+

Measured Impact

+
+

For a typical project:

+
+
+
    +
  • +

    Template-heavy design: 10+ seconds incremental rebuild

    +
  • +
  • +

    Type-erased boundaries: < 1 second incremental rebuild

    +
  • +
+
+
+

The difference grows with project size.

+
+
+
+
+
+

Transport Independence

+
+
+

Type erasure decouples your code from specific transport implementations:

+
+
+
+
// Your library code
+task<> send_message(any_write_sink& sink, message const& msg)
+{
+    co_await sink.write(make_buffer(msg.header));
+    co_await sink.write(make_buffer(msg.body), true);
+}
+
+
+
+

Callers provide any conforming implementation:

+
+
+
+
// TCP socket
+tcp::socket socket;
+any_write_sink sink{socket};
+send_message(sink, msg);
+
+// TLS stream
+tls::stream stream;
+any_write_sink sink{stream};
+send_message(sink, msg);
+
+// HTTP chunked encoding
+chunked_sink chunked{underlying};
+any_write_sink sink{chunked};
+send_message(sink, msg);
+
+// Test mock
+test::write_sink mock;
+any_write_sink sink{mock};
+send_message(sink, msg);
+
+
+
+

Same send_message function, different transports—compile once, use everywhere.

+
+
+
+
+

API Design Guidelines

+
+
+

Accept Type-Erased References

+
+
+
// Good: accepts any stream
+task<> process(any_stream& stream);
+
+// Avoid: forces specific type
+task<> process(tcp::socket& socket);
+
+
+
+
+

Wrap at Call Site

+
+
+
void caller(tcp::socket& socket)
+{
+    any_stream stream{socket};  // Wrap here
+    process(stream);            // Call with erased type
+}
+
+
+
+

The wrapper creation is explicit and localized.

+
+
+
+

Return Concrete Types (Usually)

+
+
+
// OK: factory returns concrete type
+tcp::socket create_socket();
+
+// Then caller wraps if needed
+auto socket = create_socket();
+any_stream stream{socket};
+
+
+
+

Returning type-erased values forces heap allocation. Return concrete types when the caller knows what they need.

+
+
+
+
+
+

Example: Library API

+
+
+
+
// http_client.hpp
+#pragma once
+#include <boost/capy/io/any_read_source.hpp>
+#include <boost/capy/io/any_write_sink.hpp>
+
+struct http_request
+{
+    std::string method;
+    std::string url;
+    std::map<std::string, std::string> headers;
+};
+
+struct http_response
+{
+    int status_code;
+    std::map<std::string, std::string> headers;
+    any_read_source body;  // Body is a source, not a buffer
+};
+
+// Send request, receive response
+// Works with any transport that provides any_stream
+task<http_response> send_request(any_stream& conn, http_request const& req);
+
+
+
+

Users don’t need to know how HTTP is implemented:

+
+
+
+
// User code
+tcp::socket socket;
+// ... connect ...
+
+any_stream conn{socket};
+auto response = co_await send_request(conn, {
+    .method = "GET",
+    .url = "/api/data"
+});
+
+// Read body through type-erased source
+flat_dynamic_buffer buf;
+co_await read(response.body, buf);
+
+
+
+

The HTTP library is isolated from transport details. It compiles once. Users bring their own transport.

+
+
+
+
+

Wrapper Overhead

+
+
+

Type erasure has runtime cost:

+
+
+
    +
  • +

    Virtual dispatch for each operation

    +
  • +
  • +

    Extra indirection through wrapper

    +
  • +
+
+
+

But the cost is typically negligible compared to I/O latency. A nanosecond of dispatch overhead is invisible next to microsecond network operations.

+
+
+

When profiling shows wrapper overhead matters:

+
+
+
    +
  1. +

    Consider batching operations

    +
  2. +
  3. +

    Use concrete types in hot paths

    +
  4. +
  5. +

    Accept the template cost for that code path

    +
  6. +
+
+
+
+
+

Reference

+
+
+

Type-erased wrappers are in <boost/capy/io/>:

+
+
+
    +
  • +

    any_stream

    +
  • +
  • +

    any_read_stream, any_write_stream

    +
  • +
  • +

    any_read_source, any_write_sink

    +
  • +
  • +

    any_buffer_source, any_buffer_sink

    +
  • +
+
+
+

You have now completed the Stream Concepts section. These abstractions—streams, sources, sinks, and their type-erased wrappers—form the foundation for Capy’s I/O model. Continue to Example Programs to see complete working examples.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7.intro.html b/preview/7.examples/7.intro.html new file mode 100644 index 0000000..3a31d1c --- /dev/null +++ b/preview/7.examples/7.intro.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + Example Programs :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Example Programs

+
+

The best way to learn a library is to watch it solve real problems. This section is a collection of complete, working programs that demonstrate how the pieces you have learned—​tasks, buffers, streams, cancellation, composition—​fit together in practice.

+
+
+

Every example is self-contained and compiles as a standalone program. The code is followed by detailed explanations of what it does, why it is structured that way, and what happens at each step. The examples range from minimal starting points to fully featured servers, covering real-world integration with Corosio. Start with whatever interests you most, or work through them in order for a guided tour of Capy’s capabilities.

+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7a.hello-task.html b/preview/7.examples/7a.hello-task.html new file mode 100644 index 0000000..7f787f5 --- /dev/null +++ b/preview/7.examples/7a.hello-task.html @@ -0,0 +1,553 @@ + + + + + + + + + + + + + + Hello Task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Hello Task

+
+
+
+

The minimal Capy program: a task that prints a message.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Creating a task<> coroutine

    +
  • +
  • +

    Using thread_pool as an execution context

    +
  • +
  • +

    Launching tasks with run_async

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    C++20 compiler

    +
  • +
  • +

    Capy library installed

    +
  • +
+
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <iostream>
+
+using namespace boost::capy;
+
+task<> say_hello()
+{
+    std::cout << "Hello from Capy!\n";
+    co_return;
+}
+
+int main()
+{
+    thread_pool pool;
+    run_async(pool.get_executor())(say_hello());
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(hello_task hello_task.cpp)
+target_link_libraries(hello_task PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

The Task

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

task<> is equivalent to task<void>—a coroutine that completes without returning a value. The co_return keyword marks this as a coroutine.

+
+
+

Tasks are lazy: calling say_hello() creates a task object but does not execute the body. The "Hello" message is not printed until the task is launched.

+
+
+
+

The Thread Pool

+
+
+
thread_pool pool;
+
+
+
+

thread_pool provides an execution context with worker threads. By default, it creates one thread per CPU core.

+
+
+

The pool’s destructor waits for all work to complete before returning. This ensures the program doesn’t exit while tasks are running.

+
+
+
+

Launching

+
+
+
run_async(pool.get_executor())(say_hello());
+
+
+
+

run_async bridges non-coroutine code (like main) to coroutine code. The two-call syntax:

+
+
+
    +
  1. +

    run_async(pool.get_executor()) — Creates a launcher with the executor

    +
  2. +
  3. +

    (say_hello()) — Accepts the task and starts execution

    +
  4. +
+
+
+

The task runs on one of the pool’s worker threads.

+
+
+
+
+
+

Output

+
+
+
+
Hello from Capy!
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Modify say_hello to accept a std::string_view parameter and print it

    +
  2. +
  3. +

    Create multiple tasks and launch them all

    +
  4. +
  5. +

    Add a handler to run_async that prints when the task completes

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7b.producer-consumer.html b/preview/7.examples/7b.producer-consumer.html new file mode 100644 index 0000000..044cedd --- /dev/null +++ b/preview/7.examples/7b.producer-consumer.html @@ -0,0 +1,623 @@ + + + + + + + + + + + + + + Producer-Consumer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Producer-Consumer

+
+
+
+

Two tasks communicating via an async event, with strand serialization.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Using async_event for coroutine synchronization

    +
  • +
  • +

    Running multiple concurrent tasks with when_all

    +
  • +
  • +

    Using strand to serialize access to shared state

    +
  • +
  • +

    Task-to-task communication patterns

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Hello Task

    +
  • +
  • +

    Understanding of basic task creation and launching

    +
  • +
+
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <boost/capy/ex/strand.hpp>
+#include <iostream>
+#include <latch>
+
+using namespace 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
+
+    auto on_complete = [&done](auto&&...) { done.count_down(); };  // lambda
+    auto on_error = [&done](std::exception_ptr) { done.count_down(); };  // lambda
+
+    async_event data_ready;  // async_event
+    int shared_value = 0;    // int
+
+    auto producer = [&]() -> 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<> {
+        std::cout << "Consumer: waiting for data...\n";
+        co_await data_ready.wait();
+        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());
+    };
+
+    run_async(s, on_complete, on_error)(run_both());
+
+    done.wait();  // Block until tasks complete
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(producer_consumer producer_consumer.cpp)
+target_link_libraries(producer_consumer PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

The Strand

+
+
+
strand s{pool.get_executor()};  // strand - serializes execution
+
+
+
+

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.

+
+
+
+

The Event

+
+
+
async_event data_ready;  // async_event
+
+
+
+

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.

+
+
+
+

Producer

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

The producer prepares data and signals completion by calling set().

+
+
+
+

Consumer

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

The consumer waits until the event is set. The co_await data_ready.wait() suspends until set() is called.

+
+
+
+

Running Both

+
+
+
// 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());
+};
+
+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.

+
+
+
+

Completion Synchronization

+
+
+
std::latch done(1);  // std::latch - wait for completion
+auto on_complete = [&done](auto&&...) { done.count_down(); };
+auto on_error = [&done](std::exception_ptr) { done.count_down(); };
+// ...
+done.wait();  // Block until tasks complete
+
+
+
+

The std::latch ensures main() waits for the tasks to complete before returning.

+
+
+
+
+
+

Output

+
+
+
+
Producer: preparing data...
+Producer: data ready, signaling
+Consumer: waiting for data...
+Consumer: received value 42
+
+
+
+

(Output order may vary due to concurrent execution)

+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add multiple consumers that all wait for the same event

    +
  2. +
  3. +

    Create a producer that sets the event multiple times (use a loop with a new event each iteration)

    +
  4. +
  5. +

    Add error handling—what happens if the producer throws?

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7c.buffer-composition.html b/preview/7.examples/7c.buffer-composition.html new file mode 100644 index 0000000..617c574 --- /dev/null +++ b/preview/7.examples/7c.buffer-composition.html @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + Buffer Composition :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Buffer Composition

+
+
+
+

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

    +
  • +
  • +

    Zero-allocation buffer sequence patterns

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <iostream>
+#include <string>
+#include <array>
+#include <vector>
+
+using namespace boost::capy;
+
+void demonstrate_single_buffers()
+{
+    std::cout << "=== Single Buffer Examples ===\n\n";
+
+    // Create buffers from various sources
+    std::string str = "Hello, World!";
+    char arr[] = "Array data";
+    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
+
+    std::cout << "String buffer: " << str_buf.size() << " bytes\n";
+    std::cout << "Array buffer:  " << arr_buf.size() << " bytes\n";
+    std::cout << "Vector buffer: " << vec_buf.size() << " bytes\n";
+}
+
+void demonstrate_buffer_pair()
+{
+    std::cout << "\n=== Buffer Pair (Scatter/Gather) ===\n\n";
+
+    // 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)
+    }};
+
+    // Calculate total size
+    std::size_t total = buffer_size(message);
+    std::cout << "Total message size: " << total << " bytes\n";
+    std::cout << "Buffer count: " << buffer_length(message) << "\n";
+
+    // Iterate through buffers
+    std::cout << "\nBuffer contents:\n";
+    for (auto const& buf : message)  // const_buffer const&
+    {
+        std::cout << "  [" << buf.size() << " bytes]: ";
+        std::cout.write(static_cast<char const*>(buf.data()), buf.size());
+        std::cout << "\n";
+    }
+}
+
+void demonstrate_buffer_array()
+{
+    std::cout << "\n=== Multi-Buffer Array ===\n\n";
+
+    // Use std::array for more than 2 buffers
+    std::string status = "HTTP/1.1 200 OK\r\n";
+    std::string content_type = "Content-Type: application/json\r\n";
+    std::string server = "Server: Capy/1.0\r\n";
+    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::size_t total = buffer_size(http_response);
+    std::cout << "HTTP response size: " << total << " bytes\n";
+    std::cout << "Buffer count: " << buffer_length(http_response) << "\n";
+
+    // In real code with streams:
+    // co_await write(stream, http_response);
+    // This performs scatter/gather I/O - single syscall for all buffers
+}
+
+void demonstrate_mutable_buffers()
+{
+    std::cout << "\n=== Mutable Buffer Example ===\n\n";
+
+    // Mutable buffers for receiving data
+    char buf1[64];
+    char buf2[64];
+
+    mutable_buffer_pair recv_buffers = {{
+        mutable_buffer(buf1, sizeof(buf1)),
+        mutable_buffer(buf2, sizeof(buf2))
+    }};
+
+    std::cout << "Prepared " << buffer_length(recv_buffers)
+              << " buffers with " << buffer_size(recv_buffers)
+              << " bytes total capacity\n";
+
+    // In real code:
+    // auto [ec, n] = co_await stream.read_some(recv_buffers);
+}
+
+int main()
+{
+    demonstrate_single_buffers();
+    demonstrate_buffer_pair();
+    demonstrate_buffer_array();
+    demonstrate_mutable_buffers();
+
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(buffer_composition buffer_composition.cpp)
+target_link_libraries(buffer_composition PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

Creating Buffers

+
+
+
auto str_buf = make_buffer(str);  // mutable_buffer
+auto arr_buf = 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

+
+
+
const_buffer_pair message = {{
+    make_buffer(header),
+    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.

+
+
+
+

Multi-Buffer Arrays

+
+
+
std::array<const_buffer, 5> http_response = {{
+    make_buffer(status),
+    make_buffer(content_type),
+    // ...
+}};
+
+
+
+

For more than two buffers, use std::array directly. Buffer sequences support buffer_size() and buffer_length() for querying total bytes and buffer count.

+
+
+
+

Scatter/Gather I/O

+
+
+
co_await write(stream, http_response);
+
+
+
+

When you write a buffer sequence, the OS receives all buffers in a single system call. This is scatter/gather I/O:

+
+
+
    +
  • +

    No intermediate buffer allocation

    +
  • +
  • +

    No copying data together

    +
  • +
  • +

    Single syscall for multiple buffers

    +
  • +
+
+
+
+
+
+

Output

+
+
+
+
=== Single Buffer Examples ===
+
+String buffer: 13 bytes
+Array buffer:  10 bytes
+Vector buffer: 6 bytes
+
+=== Buffer Pair (Scatter/Gather) ===
+
+Total message size: 41 bytes
+Buffer count: 2
+
+Buffer contents:
+  [28 bytes]: Content-Type: text/plain
+
+
+  [13 bytes]: Hello, World!
+
+=== Multi-Buffer Array ===
+
+HTTP response size: 84 bytes
+Buffer count: 5
+
+=== Mutable Buffer Example ===
+
+Prepared 2 buffers with 128 bytes total capacity
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Create a function that takes any ConstBufferSequence and prints its contents

    +
  2. +
  3. +

    Measure the difference between copying data into a single buffer vs. using cat()

    +
  4. +
  5. +

    Implement a simple message framing protocol using buffer composition

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7d.mock-stream-testing.html b/preview/7.examples/7d.mock-stream-testing.html new file mode 100644 index 0000000..499be1e --- /dev/null +++ b/preview/7.examples/7d.mock-stream-testing.html @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + Mock Stream Testing :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Mock Stream Testing

+
+
+
+

Unit testing protocol code with mock streams and error injection.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Using test::read_stream and test::write_stream

    +
  • +
  • +

    Error injection with fuse

    +
  • +
  • +

    Synchronous testing with run_blocking

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <boost/capy/test/stream.hpp>
+#include <boost/capy/test/fuse.hpp>
+#include <boost/capy/io/any_stream.hpp>
+#include <boost/capy/cond.hpp>
+#include <iostream>
+#include <cassert>
+#include <cctype>
+
+using namespace boost::capy;
+
+// A simple protocol: read until newline, echo back uppercase
+// Takes any_stream& so the function is transport-independent
+task<bool> echo_line_uppercase(any_stream& stream)
+{
+    std::string line;
+    char c;
+
+    // Read character by character until newline
+    while (true)
+    {
+        // ec: std::error_code, n: std::size_t
+        auto [ec, n] = co_await stream.read_some(mutable_buffer(&c, 1));
+
+        if (ec)
+        {
+            if (ec == cond::eof)
+                break;
+            co_return false;
+        }
+
+        if (c == '\n')
+            break;
+
+        line += static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
+    }
+
+    line += '\n';
+
+    // Echo uppercase - loop until all bytes written
+    std::size_t written = 0;  // std::size_t - total bytes written
+    while (written < line.size())
+    {
+        // wec: std::error_code, wn: std::size_t
+        auto [wec, wn] = co_await stream.write_some(
+            const_buffer(line.data() + written, line.size() - written));
+
+        if (wec)
+            co_return false;
+
+        written += wn;
+    }
+
+    co_return true;
+}
+
+void test_happy_path()
+{
+    std::cout << "Test: happy path\n";
+
+    // Use fuse in disarmed mode (no error injection) for happy path
+    test::fuse f;  // test::fuse
+    test::stream mock(f);  // test::stream
+    mock.provide("hello\n");
+
+    // Wrap mock in any_stream using pointer construction for reference semantics
+    any_stream stream{&mock};  // any_stream
+
+    bool result = false;  // bool
+    test::run_blocking([&](bool r) { result = r; })(echo_line_uppercase(stream));
+
+    assert(result == true);
+    assert(mock.data() == "HELLO\n");
+
+    std::cout << "  PASSED\n";
+}
+
+void test_partial_reads()
+{
+    std::cout << "Test: partial reads (1 byte at a time)\n";
+
+    // Use fuse in disarmed mode (no error injection)
+    test::fuse f;  // test::fuse
+    // Mock returns at most 1 byte per read_some
+    test::stream mock(f, 1);  // test::stream, max_read_size = 1
+    mock.provide("hi\n");
+
+    // Wrap mock in any_stream using pointer construction for reference semantics
+    any_stream stream{&mock};  // any_stream
+
+    bool result = false;  // bool
+    test::run_blocking([&](bool r) { result = r; })(echo_line_uppercase(stream));
+
+    assert(result == true);
+    assert(mock.data() == "HI\n");
+
+    std::cout << "  PASSED\n";
+}
+
+void test_with_error_injection()
+{
+    std::cout << "Test: error injection\n";
+
+    int success_count = 0;
+    int error_count = 0;
+
+    // fuse::armed runs the test repeatedly, failing at each
+    // operation point until all paths are covered
+    test::fuse f;  // test::fuse
+    auto r = f.armed([&](test::fuse&) -> task<> {  // fuse::result
+        test::stream mock(f);  // test::stream
+        mock.provide("test\n");
+
+        // Wrap mock in any_stream using pointer construction for reference semantics
+        any_stream stream{&mock};  // any_stream
+
+        // Run the protocol - fuse will inject errors at each step
+        bool result = co_await echo_line_uppercase(stream);  // bool
+
+        // Either succeeds with correct output, or fails cleanly
+        if (result)
+        {
+            ++success_count;
+            assert(mock.data() == "TEST\n");
+        }
+        else
+        {
+            ++error_count;
+        }
+    });
+
+    // Verify that fuse testing exercised both paths
+    std::cout << "  Runs: " << (success_count + error_count)
+              << " (success=" << success_count
+              << ", error=" << error_count << ")\n";
+
+    assert(r.success);
+    assert(success_count > 0);  // At least one successful run
+    assert(error_count > 0);    // At least one error-injected run
+
+    std::cout << "  PASSED (all error paths tested)\n";
+}
+
+int main()
+{
+    test_happy_path();
+    test_partial_reads();
+    test_with_error_injection();
+
+    std::cout << "\nAll tests passed!\n";
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(mock_stream_testing mock_stream_testing.cpp)
+target_link_libraries(mock_stream_testing PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

Mock Streams

+
+
+
test::fuse f;  // test::fuse
+test::stream mock(f);  // test::stream
+mock.provide("hello\n");
+
+
+
+

test::stream is a bidirectional mock that satisfies both ReadStream and WriteStream:

+
+
+
    +
  • +

    Constructor takes a fuse& for error injection

    +
  • +
  • +

    provide(data) — Supplies data for reads

    +
  • +
  • +

    data() — Returns data written to the mock

    +
  • +
  • +

    Second constructor parameter controls max bytes per operation

    +
  • +
+
+
+
+

Type-Erased Streams

+
+
+
// Wrap mock in any_stream using pointer construction for reference semantics
+any_stream stream{&mock};  // any_stream
+
+
+
+

Use pointer construction (&mock) so the any_stream wrapper references the mock without taking ownership. This allows inspecting mock.data() after operations.

+
+
+
+

Synchronous Testing

+
+
+
bool result = false;  // bool
+test::run_blocking([&](bool r) { result = r; })(echo_line_uppercase(stream));
+
+
+
+

run_blocking executes a coroutine synchronously, blocking until complete. Pass a handler to capture the result.

+
+
+
+

Error Injection

+
+
+
test::fuse f;  // test::fuse
+auto r = f.armed([&](test::fuse&) -> task<> {
+    test::stream mock(f);  // test::stream
+    // ... run test ...
+});
+
+
+
+

fuse::armed runs the test function repeatedly, injecting errors at each operation point:

+
+
+
    +
  1. +

    First run: error at operation 1

    +
  2. +
  3. +

    Second run: error at operation 2

    +
  4. +
  5. +

    …​and so on until all operations succeed

    +
  6. +
+
+
+

This systematically tests all error handling paths.

+
+
+
+
+
+

Output

+
+
+
+
Test: happy path
+  PASSED
+Test: partial reads (1 byte at a time)
+  PASSED
+Test: error injection
+  Runs: 9 (success=2, error=7)
+  PASSED (all error paths tested)
+
+All tests passed!
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add a test for EOF handling (what if input doesn’t end with newline?)

    +
  2. +
  3. +

    Test with different max_read_size values

    +
  4. +
  5. +

    Add a test for write errors using test::write_stream

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7e.type-erased-echo.html b/preview/7.examples/7e.type-erased-echo.html new file mode 100644 index 0000000..5b5987e --- /dev/null +++ b/preview/7.examples/7e.type-erased-echo.html @@ -0,0 +1,667 @@ + + + + + + + + + + + + + + Type-Erased Echo :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Type-Erased Echo

+
+
+
+

Echo server demonstrating the compilation firewall pattern.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Using any_stream for transport-independent code

    +
  • +
  • +

    Physical isolation through separate compilation

    +
  • +
  • +

    Build time benefits of type erasure

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+

echo.hpp

+
+
+
#ifndef ECHO_HPP
+#define ECHO_HPP
+
+#include <boost/capy/io/any_stream.hpp>
+#include <boost/capy/task.hpp>
+
+namespace myapp {
+
+// Type-erased interface: no template dependencies
+boost::capy::task<> echo_session(boost::capy::any_stream& stream);
+
+} // namespace myapp
+
+#endif
+
+
+
+
+

echo.cpp

+
+
+
#include "echo.hpp"
+#include <boost/capy/read.hpp>
+#include <boost/capy/write.hpp>
+#include <boost/capy/cond.hpp>
+#include <boost/capy/buffers/make_buffer.hpp>
+
+namespace myapp {
+
+using namespace boost::capy;
+
+task<> echo_session(any_stream& stream)
+{
+    char buffer[1024];
+
+    for (;;)
+    {
+        // Read some data
+        // ec: std::error_code, n: std::size_t
+        auto [ec, n] = co_await stream.read_some(make_buffer(buffer));
+
+        if (ec == cond::eof)
+            co_return;  // Client closed connection
+
+        if (ec)
+            throw std::system_error(ec);
+
+        // Echo it back
+        // wec: std::error_code, wn: std::size_t
+        auto [wec, wn] = co_await write(stream, const_buffer(buffer, n));
+
+        if (wec)
+            throw std::system_error(wec);
+    }
+}
+
+} // namespace myapp
+
+
+
+
+

main.cpp

+
+
+
#include "echo.hpp"
+#include <boost/capy.hpp>
+#include <boost/capy/test/stream.hpp>
+#include <boost/capy/test/fuse.hpp>
+#include <boost/capy/test/run_blocking.hpp>
+#include <iostream>
+
+using namespace boost::capy;
+
+void test_with_mock()
+{
+    test::fuse f;
+    test::stream mock(f);
+    mock.provide("Hello, ");
+    mock.provide("World!\n");
+    // Stream returns eof when no more data is available
+
+    // Using pointer construction (&mock) for reference semantics - the
+    // wrapper does not take ownership, so mock must outlive stream.
+    any_stream stream{&mock};  // any_stream
+    test::run_blocking()(myapp::echo_session(stream));
+
+    std::cout << "Echo output: " << mock.data() << "\n";
+}
+
+// With real sockets (using Corosio), you would write:
+//
+// task<> handle_client(corosio::tcp::socket socket)
+// {
+//     // Value construction moves socket into wrapper (transfers ownership)
+//     any_stream stream{std::move(socket)};
+//     co_await myapp::echo_session(stream);
+// }
+
+int main()
+{
+    test_with_mock();
+    return 0;
+}
+
+
+
+
+
+
+

Build

+
+
+
+
add_library(echo_lib echo.cpp)
+target_link_libraries(echo_lib PUBLIC capy)
+
+add_executable(echo_demo main.cpp)
+target_link_libraries(echo_demo PRIVATE echo_lib)
+
+
+
+
+
+

Walkthrough

+
+
+

The Interface

+
+
+
// echo.hpp
+task<> echo_session(any_stream& stream);
+
+
+
+

The header declares only the signature. It includes any_stream and task, but no concrete transport types.

+
+
+

Clients of this header:

+
+
+
    +
  • +

    Can call echo_session with any stream

    +
  • +
  • +

    Do not depend on implementation details

    +
  • +
  • +

    Do not recompile when implementation changes

    +
  • +
+
+
+
+

The Implementation

+
+
+
// echo.cpp
+task<> echo_session(any_stream& stream)
+{
+    // Full implementation here
+}
+
+
+
+

The implementation:

+
+
+
    +
  • +

    Lives in a separate .cpp file

    +
  • +
  • +

    Compiles once

    +
  • +
  • +

    Can include any headers it needs internally

    +
  • +
+
+
+
+

Build Isolation

+
+

When you change echo.cpp:

+
+
+
    +
  • +

    Only echo.cpp recompiles

    +
  • +
  • +

    main.cpp and other clients do not recompile

    +
  • +
  • +

    Link step updates the binary

    +
  • +
+
+
+

This scales: in large projects, changes to implementation files don’t cascade through dependencies.

+
+
+
+
+
+

Output

+
+
+
+
Echo output: Hello, World!
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add logging to echo_session and observe that clients don’t recompile

    +
  2. +
  3. +

    Create a second implementation file with different behavior (e.g., uppercase echo)

    +
  4. +
  5. +

    Measure compile times with and without type erasure in a larger project

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7f.timeout-cancellation.html b/preview/7.examples/7f.timeout-cancellation.html new file mode 100644 index 0000000..9e66269 --- /dev/null +++ b/preview/7.examples/7f.timeout-cancellation.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + + Timeout with Cancellation :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Timeout with Cancellation

+
+
+
+

Using stop tokens to implement operation timeouts.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Creating and using std::stop_source

    +
  • +
  • +

    Checking stop_requested() in coroutines

    +
  • +
  • +

    Cancellation patterns

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <boost/capy/test/stream.hpp>
+#include <boost/capy/test/run_blocking.hpp>
+#include <chrono>
+#include <iostream>
+#include <latch>
+#include <thread>
+
+using namespace boost::capy;
+
+// A slow operation that respects cancellation
+task<std::string> slow_fetch(int steps)
+{
+    auto token = co_await this_coro::stop_token;  // std::stop_token
+    std::string result;
+
+    for (int i = 0; i < steps; ++i)
+    {
+        // Check cancellation before each step
+        if (token.stop_requested())
+        {
+            std::cout << "  Cancelled at step " << i << std::endl;
+            throw std::system_error(
+                make_error_code(std::errc::operation_canceled));
+        }
+
+        result += "step" + std::to_string(i) + " ";
+
+        // Simulate slow work (in real code, this would be I/O)
+        std::this_thread::sleep_for(std::chrono::milliseconds(10));
+        std::cout << "  Completed step " << i << std::endl;
+
+        // Yield to allow stop request to be processed before next check
+        std::this_thread::sleep_for(std::chrono::milliseconds(15));
+    }
+
+    co_return result;
+}
+
+// Run with timeout (conceptual - real implementation needs timer)
+task<std::optional<std::string>> fetch_with_timeout()
+{
+    auto token = co_await this_coro::stop_token;  // std::stop_token
+
+    try
+    {
+        auto result = co_await slow_fetch(5);  // std::string
+        co_return result;
+    }
+    catch (std::system_error const& e)
+    {
+        if (e.code() == std::errc::operation_canceled)
+            co_return std::nullopt;
+        throw;
+    }
+}
+
+void demo_normal_completion()
+{
+    std::cout << "Demo: Normal completion\n";
+
+    thread_pool pool;
+    std::stop_source source;
+    std::latch done(1);  // std::latch - wait for 1 task
+
+    run_async(pool.get_executor(), source.get_token(),
+        [&done](std::optional<std::string> result) {
+            if (result)
+                std::cout << "Result: " << *result << "\n";
+            else
+                std::cout << "Cancelled\n";
+            done.count_down();
+        },
+        [&done](std::exception_ptr) { done.count_down(); }
+    )(fetch_with_timeout());
+
+    done.wait();  // Block until task completes
+}
+
+void demo_cancellation()
+{
+    std::cout << "\nDemo: Cancellation after 2 steps\n";
+
+    thread_pool pool;
+    std::stop_source source;
+    std::latch done(1);  // std::latch - wait for 1 task
+
+    // Launch the task
+    run_async(pool.get_executor(), source.get_token(),
+        [&done](std::optional<std::string> result) {
+            if (result)
+                std::cout << "Result: " << *result << "\n";
+            else
+                std::cout << "Cancelled (returned nullopt)\n";
+            done.count_down();
+        },
+        [&done](std::exception_ptr) { done.count_down(); }
+    )(fetch_with_timeout());
+
+    // Simulate timeout: cancel after 2 steps complete
+    // Timing: each step is 10ms work + 15ms yield = 25ms total
+    // Stop at 42ms: after step 1 print, before step 2 check
+    std::this_thread::sleep_for(std::chrono::milliseconds(42));
+    std::cout << "  Requesting stop..." << std::endl;
+    source.request_stop();
+
+    done.wait();  // Block until task completes (after cancellation)
+}
+
+// Example: Manual stop token checking
+task<int> process_items(std::vector<int> const& items)
+{
+    auto token = co_await this_coro::stop_token;  // std::stop_token
+    int sum = 0;
+
+    for (auto item : items)  // int
+    {
+        if (token.stop_requested())
+        {
+            std::cout << "Processing cancelled, partial sum: " << sum << "\n";
+            co_return sum;  // Return partial result
+        }
+
+        sum += item;
+    }
+
+    co_return sum;
+}
+
+int main()
+{
+    demo_normal_completion();
+    demo_cancellation();
+
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(timeout_cancellation timeout_cancellation.cpp)
+target_link_libraries(timeout_cancellation PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

Getting the Stop Token

+
+
+
auto token = co_await this_coro::stop_token;  // std::stop_token
+
+
+
+

Inside a task, this_coro::stop_token retrieves the stop token propagated from the caller. You can also access it through the full environment via co_await this_coro::environment.

+
+
+
+

Checking for Cancellation

+
+
+
if (token.stop_requested())
+{
+    throw std::system_error(make_error_code(std::errc::operation_canceled));
+}
+
+
+
+

Check stop_requested() at appropriate points—typically before expensive operations or at loop iterations.

+
+
+
+

Triggering Cancellation

+
+
+
std::stop_source source;
+run_async(ex, source.get_token())(my_task());
+
+// Later:
+source.request_stop();
+
+
+
+

The stop source controls the stop token. Calling request_stop() signals all holders of tokens from this source.

+
+
+
+

Partial Results

+
+
+
if (token.stop_requested())
+{
+    co_return partial_result;  // Return what we have
+}
+
+
+
+

Cancellation doesn’t have to throw. You can return partial results or a sentinel value.

+
+
+
+
+
+

Output

+
+
+
+
Demo: Normal completion
+  Completed step 0
+  Completed step 1
+  Completed step 2
+  Completed step 3
+  Completed step 4
+Result: step0 step1 step2 step3 step4
+
+Demo: Cancellation after 2 steps
+  Completed step 0
+  Completed step 1
+  Requesting stop...
+  Cancelled at step 2
+Cancelled (returned nullopt)
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Implement a retry-with-timeout pattern

    +
  2. +
  3. +

    Add cancellation support to the echo session from the previous example

    +
  4. +
  5. +

    Create a task that cancels itself after processing N items

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7g.parallel-fetch.html b/preview/7.examples/7g.parallel-fetch.html new file mode 100644 index 0000000..6b772bb --- /dev/null +++ b/preview/7.examples/7g.parallel-fetch.html @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + Parallel Fetch :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Parallel Fetch

+
+
+
+

Running multiple operations concurrently with when_all.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Using when_all to run tasks in parallel

    +
  • +
  • +

    Structured bindings for results

    +
  • +
  • +

    Error propagation in concurrent tasks

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <iostream>
+#include <latch>
+#include <string>
+
+using namespace boost::capy;
+
+// Simulated async operations
+task<int> fetch_user_id(std::string username)
+{
+    std::cout << "Fetching user ID for: " << username << "\n";
+    // In real code: co_await http_get("/users/" + username);
+    co_return static_cast<int>(username.length()) * 100;  // Fake ID
+}
+
+task<std::string> fetch_user_name(int id)
+{
+    std::cout << "Fetching name for user ID: " << id << "\n";
+    co_return "User" + std::to_string(id);
+}
+
+task<int> fetch_order_count(int user_id)
+{
+    std::cout << "Fetching order count for user: " << user_id << "\n";
+    co_return user_id / 10;  // Fake count
+}
+
+task<double> fetch_account_balance(int user_id)
+{
+    std::cout << "Fetching balance for user: " << user_id << "\n";
+    co_return user_id * 1.5;  // Fake balance
+}
+
+// Fetch all user data in parallel
+task<> fetch_user_dashboard(std::string username)
+{
+    std::cout << "\n=== Fetching dashboard for: " << username << " ===\n";
+
+    // First, get the user ID (needed for other queries)
+    int user_id = co_await fetch_user_id(username);
+    std::cout << "Got user ID: " << user_id << "\n\n";
+
+    // Now fetch all user data in parallel
+    std::cout << "Starting parallel fetches...\n";
+    // name: std::string, orders: int, balance: double
+    auto [name, orders, balance] = co_await when_all(
+        fetch_user_name(user_id),
+        fetch_order_count(user_id),
+        fetch_account_balance(user_id)
+    );
+
+    std::cout << "\nDashboard results:\n";
+    std::cout << "  Name: " << name << "\n";
+    std::cout << "  Orders: " << orders << "\n";
+    std::cout << "  Balance: $" << balance << "\n";
+}
+
+// Example with void tasks
+task<> log_access(std::string resource)
+{
+    std::cout << "Logging access to: " << resource << "\n";
+    co_return;
+}
+
+task<> update_metrics(std::string metric)
+{
+    std::cout << "Updating metric: " << metric << "\n";
+    co_return;
+}
+
+task<std::string> fetch_with_side_effects()
+{
+    std::cout << "\n=== Fetch with side effects ===\n";
+
+    // void tasks don't contribute to result tuple
+    std::tuple<std::string> results = co_await when_all(
+        log_access("api/data"),           // void - no result
+        update_metrics("api_calls"),      // void - no result
+        fetch_user_name(42)               // returns string
+    );
+    std::string data = std::get<0>(results);  // std::string
+
+    std::cout << "Data: " << data << "\n";
+    co_return data;
+}
+
+// Error handling example
+task<int> might_fail(bool should_fail, std::string name)
+{
+    std::cout << "Task " << name << " starting\n";
+
+    if (should_fail)
+    {
+        throw std::runtime_error(name + " failed!");
+    }
+
+    std::cout << "Task " << name << " completed\n";
+    co_return 42;
+}
+
+task<> demonstrate_error_handling()
+{
+    std::cout << "\n=== Error handling ===\n";
+
+    try
+    {
+        // a: int, b: int, c: int
+        auto [a, b, c] = co_await when_all(
+            might_fail(false, "A"),
+            might_fail(true, "B"),   // This one fails
+            might_fail(false, "C")
+        );
+        std::cout << "All succeeded: " << a << ", " << b << ", " << c << "\n";
+    }
+    catch (std::runtime_error const& e)
+    {
+        std::cout << "Caught error: " << e.what() << "\n";
+        // Note: when_all waits for all tasks to complete (or respond to stop)
+        // before propagating the first exception
+    }
+}
+
+int main()
+{
+    thread_pool pool;
+
+    std::latch done(3);  // std::latch - wait for 3 tasks
+
+    // Completion handlers signal the latch when each task finishes
+    // Use generic lambda to accept any result type (or no result for task<void>)
+    auto on_complete = [&done](auto&&...) { done.count_down(); };
+    auto on_error = [&done](std::exception_ptr) { done.count_down(); };
+
+    run_async(pool.get_executor(), on_complete, on_error)(fetch_user_dashboard("alice"));
+    run_async(pool.get_executor(), on_complete, on_error)(fetch_with_side_effects());
+    run_async(pool.get_executor(), on_complete, on_error)(demonstrate_error_handling());
+
+    done.wait();  // Block until all tasks complete
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(parallel_fetch parallel_fetch.cpp)
+target_link_libraries(parallel_fetch PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

Basic when_all

+
+
+
auto [name, orders, balance] = co_await when_all(
+    fetch_user_name(user_id),
+    fetch_order_count(user_id),
+    fetch_account_balance(user_id)
+);
+
+
+
+

All three tasks run concurrently. when_all completes when all tasks finish. Results are returned in a tuple matching input order.

+
+
+
+

Void Filtering

+
+
+
std::tuple<std::string> results = co_await when_all(
+    log_access("api/data"),      // void - filtered out
+    update_metrics("api_calls"), // void - filtered out
+    fetch_user_name(42)          // string - in tuple
+);
+std::string data = std::get<0>(results);  // std::string
+
+
+
+

Tasks returning void don’t contribute to the result tuple. Only non-void results appear.

+
+
+
+

Error Propagation

+
+
+
try
+{
+    auto results = co_await when_all(task_a(), task_b(), task_c());
+}
+catch (...)
+{
+    // First exception is rethrown
+    // All tasks complete before exception propagates
+}
+
+
+
+

When a task throws:

+
+
+
    +
  1. +

    The exception is captured

    +
  2. +
  3. +

    Stop is requested for siblings

    +
  4. +
  5. +

    All tasks complete (or respond to stop)

    +
  6. +
  7. +

    First exception is rethrown

    +
  8. +
+
+
+
+
+
+

Output

+
+
+
+
=== Fetching dashboard for: alice ===
+Fetching user ID for: alice
+Got user ID: 500
+
+Starting parallel fetches...
+Fetching name for user ID: 500
+Fetching order count for user: 500
+Fetching balance for user: 500
+
+Dashboard results:
+  Name: User500
+  Orders: 50
+  Balance: $750
+
+=== Fetch with side effects ===
+Logging access to: api/data
+Updating metric: api_calls
+Fetching name for user ID: 42
+Data: User42
+
+=== Error handling ===
+Task A starting
+Task B starting
+Task C starting
+Task A completed
+Task C completed
+Caught error: B failed!
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add timing to see the parallel speedup vs sequential execution

    +
  2. +
  3. +

    Implement a "fan-out/fan-in" pattern that processes a list of items in parallel

    +
  4. +
  5. +

    Add cancellation support so remaining tasks can exit early on error

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7h.custom-dynamic-buffer.html b/preview/7.examples/7h.custom-dynamic-buffer.html new file mode 100644 index 0000000..e5f1c50 --- /dev/null +++ b/preview/7.examples/7h.custom-dynamic-buffer.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + + Custom Dynamic Buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Custom Dynamic Buffer

+
+
+
+

Implementing the DynamicBuffer concept for a custom allocation strategy.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Implementing the DynamicBuffer concept

    +
  • +
  • +

    Understanding prepare, commit, consume lifecycle

    +
  • +
  • +

    Custom memory management for I/O

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <boost/capy/test/run_blocking.hpp>
+#include <boost/capy/test/stream.hpp>
+#include <boost/capy/test/fuse.hpp>
+#include <boost/capy/cond.hpp>
+#include <iostream>
+#include <vector>
+#include <cassert>
+#include <cstring>
+
+using namespace boost::capy;
+
+// Custom dynamic buffer with statistics tracking
+class tracked_buffer
+{
+    std::vector<char> storage_;
+    std::size_t read_pos_ = 0;   // Start of readable data
+    std::size_t write_pos_ = 0;  // End of readable data
+    std::size_t max_size_;
+
+    // Statistics
+    std::size_t total_prepared_ = 0;
+    std::size_t total_committed_ = 0;
+    std::size_t total_consumed_ = 0;
+
+public:
+    explicit tracked_buffer(std::size_t max_size = 65536)
+        : max_size_(max_size)
+    {
+        storage_.reserve(1024);
+    }
+
+    // === DynamicBuffer interface ===
+
+    // Consumer: readable data
+    const_buffer data() const noexcept
+    {
+        return const_buffer(
+            storage_.data() + read_pos_,
+            write_pos_ - read_pos_);
+    }
+
+    // Capacity queries
+    std::size_t size() const noexcept
+    {
+        return write_pos_ - read_pos_;
+    }
+
+    std::size_t max_size() const noexcept
+    {
+        return max_size_;
+    }
+
+    std::size_t capacity() const noexcept
+    {
+        return storage_.capacity() - read_pos_;
+    }
+
+    // Producer: prepare space for writing
+    mutable_buffer prepare(std::size_t n)
+    {
+        total_prepared_ += n;
+
+        // Compact if needed
+        if (storage_.size() + n > storage_.capacity() && read_pos_ > 0)
+        {
+            compact();
+        }
+
+        // Grow if needed
+        std::size_t required = write_pos_ + n;
+        if (required > max_size_)
+            throw std::length_error("tracked_buffer: max_size exceeded");
+
+        if (required > storage_.size())
+            storage_.resize(required);
+
+        return mutable_buffer(
+            storage_.data() + write_pos_,
+            n);
+    }
+
+    // Producer: mark bytes as written
+    void commit(std::size_t n)
+    {
+        total_committed_ += n;
+        write_pos_ += n;
+    }
+
+    // Consumer: mark bytes as processed
+    void consume(std::size_t n)
+    {
+        std::size_t actual = std::min(n, size());  // std::size_t
+        total_consumed_ += actual;
+        read_pos_ += actual;
+
+        if (read_pos_ == write_pos_)
+        {
+            // Buffer empty, reset positions
+            read_pos_ = 0;
+            write_pos_ = 0;
+        }
+    }
+
+    // === Statistics ===
+
+    void print_stats() const
+    {
+        std::cout << "Buffer statistics:\n"
+                  << "  Total prepared:  " << total_prepared_ << " bytes\n"
+                  << "  Total committed: " << total_committed_ << " bytes\n"
+                  << "  Total consumed:  " << total_consumed_ << " bytes\n"
+                  << "  Current size:    " << size() << " bytes\n"
+                  << "  Capacity:        " << capacity() << " bytes\n";
+    }
+
+private:
+    void compact()
+    {
+        if (read_pos_ == 0)
+            return;
+
+        std::size_t len = write_pos_ - read_pos_;
+        std::memmove(storage_.data(), storage_.data() + read_pos_, len);
+        read_pos_ = 0;
+        write_pos_ = len;
+    }
+};
+
+// Demonstrate using the custom buffer
+task<> read_into_tracked_buffer(test::stream& stream, tracked_buffer& buffer)
+{
+    // Read data in chunks
+    while (true)
+    {
+        auto space = buffer.prepare(256);  // mutable_buffer
+        // ec: std::error_code, n: std::size_t
+        auto [ec, n] = co_await stream.read_some(space);
+
+        if (ec == cond::eof)
+            break;
+
+        if (ec)
+            throw std::system_error(ec);
+
+        buffer.commit(n);
+
+        std::cout << "Read " << n << " bytes, buffer size now: "
+                  << buffer.size() << "\n";
+    }
+}
+
+void demo_tracked_buffer()
+{
+    std::cout << "=== Tracked Buffer Demo ===\n\n";
+
+    // Setup mock stream with test data
+    test::fuse f;
+    test::stream mock(f);
+    mock.provide("Hello, ");
+    mock.provide("World! ");
+    mock.provide("This is a test of the custom buffer.\n");
+    // Stream returns eof when data is exhausted
+
+    tracked_buffer buffer;
+
+    test::run_blocking()(read_into_tracked_buffer(mock, buffer));
+
+    std::cout << "\nFinal buffer contents: ";
+    auto data = buffer.data();  // const_buffer
+    std::cout.write(static_cast<char const*>(data.data()), data.size());
+    std::cout << "\n\n";
+
+    buffer.print_stats();
+
+    // Consume some data
+    std::cout << "\nConsuming 7 bytes...\n";
+    buffer.consume(7);
+    buffer.print_stats();
+}
+
+int main()
+{
+    demo_tracked_buffer();
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(custom_dynamic_buffer custom_dynamic_buffer.cpp)
+target_link_libraries(custom_dynamic_buffer PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

DynamicBuffer Requirements

+
+

A DynamicBuffer must provide:

+
+
+
+
// Consumer interface
+const_buffer data() const;      // Readable data
+void consume(std::size_t n);    // Mark bytes as processed
+
+// Producer interface
+mutable_buffer prepare(std::size_t n);  // Space for writing
+void commit(std::size_t n);             // Mark bytes as written
+
+// Capacity queries
+std::size_t size() const;       // Readable bytes
+std::size_t max_size() const;   // Maximum allowed
+std::size_t capacity() const;   // Currently allocated
+
+
+
+
+

The Producer/Consumer Flow

+
+
+
// 1. Producer prepares space
+auto space = buffer.prepare(256);  // mutable_buffer
+
+// 2. Data is written into space
+// ec: std::error_code, n: std::size_t
+auto [ec, n] = co_await stream.read_some(space);
+
+// 3. Producer commits written bytes
+buffer.commit(n);
+
+// 4. Consumer reads data
+auto data = buffer.data();  // const_buffer
+process(data);
+
+// 5. Consumer marks bytes as processed
+buffer.consume(processed_bytes);
+
+
+
+
+

Memory Management

+
+

The tracked_buffer implementation:

+
+
+
    +
  • +

    Uses a single contiguous vector

    +
  • +
  • +

    Tracks read and write positions

    +
  • +
  • +

    Compacts when needed to reuse space

    +
  • +
  • +

    Grows on demand up to max_size

    +
  • +
+
+
+
+
+
+

Output

+
+
+
+
=== Tracked Buffer Demo ===
+
+Read 51 bytes, buffer size now: 51
+
+Final buffer contents: Hello, World! This is a test of the custom buffer.
+
+
+Buffer statistics:
+  Total prepared:  512 bytes
+  Total committed: 51 bytes
+  Total consumed:  0 bytes
+  Current size:    51 bytes
+  Capacity:        1024 bytes
+
+Consuming 7 bytes...
+Buffer statistics:
+  Total prepared:  512 bytes
+  Total committed: 51 bytes
+  Total consumed:  7 bytes
+  Current size:    44 bytes
+  Capacity:        1017 bytes
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add a "high water mark" statistic that tracks maximum buffer size reached

    +
  2. +
  3. +

    Implement a ring buffer version that never moves data

    +
  4. +
  5. +

    Add an allocator parameter for custom memory allocation

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7i.echo-server-corosio.html b/preview/7.examples/7i.echo-server-corosio.html new file mode 100644 index 0000000..920e94f --- /dev/null +++ b/preview/7.examples/7i.echo-server-corosio.html @@ -0,0 +1,691 @@ + + + + + + + + + + + + + + Echo Server with Corosio :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Echo Server with Corosio

+
+
+
+

A complete echo server using Corosio for real network I/O.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Integrating Capy with Corosio networking

    +
  • +
  • +

    Accepting TCP connections

    +
  • +
  • +

    Handling multiple clients concurrently

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+
    +
  • +

    Completed Custom Dynamic Buffer

    +
  • +
  • +

    Corosio library installed

    +
  • +
  • +

    Understanding of TCP networking basics

    +
  • +
+
+
+
+
+

Source Code

+
+
+
+
#include <boost/capy.hpp>
+#include <boost/corosio.hpp>
+#include <iostream>
+
+using namespace boost::capy;
+namespace tcp = boost::corosio::tcp;
+
+// Echo handler: receives data and sends it back
+task<> echo_session(any_stream& stream, std::string client_info)
+{
+    std::cout << "[" << client_info << "] Session started\n";
+
+    char buffer[1024];
+    std::size_t total_bytes = 0;
+
+    try
+    {
+        for (;;)
+        {
+            // Read some data
+            auto [ec, n] = co_await stream.read_some(mutable_buffer(buffer));
+
+            if (ec == cond::eof)
+            {
+                std::cout << "[" << client_info << "] Client disconnected\n";
+                break;
+            }
+
+            if (ec.failed())
+            {
+                std::cout << "[" << client_info << "] Read error: "
+                          << ec.message() << "\n";
+                break;
+            }
+
+            total_bytes += n;
+
+            // Echo it back
+            auto [wec, wn] = co_await write(stream, const_buffer(buffer, n));
+
+            if (wec.failed())
+            {
+                std::cout << "[" << client_info << "] Write error: "
+                          << wec.message() << "\n";
+                break;
+            }
+        }
+    }
+    catch (std::exception const& e)
+    {
+        std::cout << "[" << client_info << "] Exception: " << e.what() << "\n";
+    }
+
+    std::cout << "[" << client_info << "] Session ended, "
+              << total_bytes << " bytes echoed\n";
+}
+
+// Accept loop: accepts connections and spawns handlers
+task<> accept_loop(tcp::acceptor& acceptor, executor_ref ex)
+{
+    std::cout << "Server listening on port "
+              << acceptor.local_endpoint().port() << "\n";
+
+    int connection_id = 0;
+
+    for (;;)
+    {
+        // Accept a connection
+        auto [ec, socket] = co_await acceptor.async_accept();
+
+        if (ec.failed())
+        {
+            std::cout << "Accept error: " << ec.message() << "\n";
+            continue;
+        }
+
+        // Build client info string
+        auto remote = socket.remote_endpoint();
+        std::string client_info =
+            std::to_string(++connection_id) + ":" +
+            remote.address().to_string() + ":" +
+            std::to_string(remote.port());
+
+        std::cout << "[" << client_info << "] Connection accepted\n";
+
+        // Wrap socket and spawn handler
+        // Note: socket ownership transfers to the lambda
+        run_async(ex)(
+            [](tcp::socket sock, std::string info) -> task<> {
+                any_stream stream{sock};
+                co_await echo_session(stream, std::move(info));
+            }(std::move(socket), std::move(client_info))
+        );
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    try
+    {
+        // Parse port from command line
+        unsigned short port = 8080;
+        if (argc > 1)
+            port = static_cast<unsigned short>(std::stoi(argv[1]));
+
+        // Create I/O context and thread pool
+        boost::corosio::io_context ioc;
+        thread_pool pool(4);
+
+        // Create acceptor
+        tcp::endpoint endpoint(tcp::v4(), port);
+        tcp::acceptor acceptor(ioc, endpoint);
+        acceptor.set_option(tcp::acceptor::reuse_address(true));
+
+        std::cout << "Starting echo server...\n";
+
+        // Run accept loop
+        run_async(pool.get_executor())(
+            accept_loop(acceptor, pool.get_executor())
+        );
+
+        // Run the I/O context (this blocks)
+        ioc.run();
+    }
+    catch (std::exception const& e)
+    {
+        std::cerr << "Error: " << e.what() << "\n";
+        return 1;
+    }
+
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
find_package(Corosio REQUIRED)
+
+add_executable(echo_server echo_server.cpp)
+target_link_libraries(echo_server PRIVATE capy Corosio::corosio)
+
+
+
+
+
+

Walkthrough

+
+
+

TCP Acceptor

+
+
+
tcp::endpoint endpoint(tcp::v4(), port);
+tcp::acceptor acceptor(ioc, endpoint);
+
+
+
+

The acceptor listens for incoming connections on the specified port.

+
+
+
+

Accept Loop

+
+
+
for (;;)
+{
+    auto [ec, socket] = co_await acceptor.async_accept();
+    // ... handle connection ...
+}
+
+
+
+

The accept loop runs forever, accepting connections and spawning handlers. Each connection runs in its own task.

+
+
+
+

Type Erasure

+
+
+
any_stream stream{sock};
+co_await echo_session(stream, std::move(info));
+
+
+
+

The echo_session function accepts any_stream&. The concrete tcp::socket is wrapped at the call site. This keeps the echo logic transport-independent.

+
+
+
+

Concurrent Clients

+
+

Each client connection spawns a new task via run_async. Multiple clients are handled concurrently on the thread pool.

+
+
+
+
+
+

Testing

+
+
+

Start the server:

+
+
+
+
$ ./echo_server 8080
+Starting echo server...
+Server listening on port 8080
+
+
+
+

Connect with netcat:

+
+
+
+
$ nc localhost 8080
+Hello
+Hello
+World
+World
+^C
+
+
+
+

Server output:

+
+
+
+
[1:127.0.0.1:54321] Connection accepted
+[1:127.0.0.1:54321] Session started
+[1:127.0.0.1:54321] Client disconnected
+[1:127.0.0.1:54321] Session ended, 12 bytes echoed
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add a connection limit with graceful rejection

    +
  2. +
  3. +

    Implement a simple command protocol (e.g., ECHO, QUIT, STATS)

    +
  4. +
  5. +

    Add TLS support using Corosio’s TLS streams

    +
  6. +
+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/7.examples/7j.stream-pipeline.html b/preview/7.examples/7j.stream-pipeline.html new file mode 100644 index 0000000..7884e29 --- /dev/null +++ b/preview/7.examples/7j.stream-pipeline.html @@ -0,0 +1,893 @@ + + + + + + + + + + + + + + Stream Pipeline :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Stream Pipeline

+
+
+
+

Data transformation through a pipeline of sources and sinks.

+
+
+
+
+

What You Will Learn

+
+
+
    +
  • +

    Building processing pipelines

    +
  • +
  • +

    Using BufferSource and BufferSink concepts

    +
  • +
  • +

    Chaining transformations

    +
  • +
+
+
+
+
+

Prerequisites

+
+
+ +
+
+
+
+

Source Code

+
+
+
+
//
+// Stream Pipeline Example
+//
+// This example demonstrates chaining buffer sources to create a data
+// processing pipeline. Data flows through transform stages:
+//
+//   input -> uppercase_transform -> line_numbering_transform -> output
+//
+// Each transform is a BufferSource that wraps an upstream any_buffer_source,
+// enabling type-erased composition of arbitrary transform chains.
+//
+
+#include <boost/capy.hpp>
+#include <boost/capy/test/run_blocking.hpp>
+#include <boost/capy/test/buffer_source.hpp>
+#include <boost/capy/test/write_sink.hpp>
+#include <boost/capy/io/any_buffer_source.hpp>
+#include <boost/capy/io/any_write_sink.hpp>
+#include <iostream>
+#include <algorithm>
+#include <cctype>
+#include <system_error>
+
+using namespace boost::capy;
+
+// A transform stage that converts to uppercase
+class uppercase_transform
+{
+    any_buffer_source* source_;  // any_buffer_source*
+    std::vector<char> buffer_;   // std::vector<char>
+    std::size_t consumed_ = 0;   // std::size_t
+    bool exhausted_ = false;     // bool
+
+public:
+    explicit uppercase_transform(any_buffer_source& source)
+        : source_(&source)
+    {
+    }
+
+    // BufferSource::consume - advance past processed bytes
+    void consume(std::size_t n) noexcept
+    {
+        consumed_ += n;
+        if (consumed_ >= buffer_.size())
+        {
+            buffer_.clear();
+            consumed_ = 0;
+        }
+    }
+
+    // BufferSource::pull - returns task<> to enable co_await on upstream
+    io_task<std::span<const_buffer>>
+    pull(std::span<const_buffer> dest)
+    {
+        // Already have unconsumed data?
+        if (consumed_ < buffer_.size())
+        {
+            if (dest.empty())
+                co_return {std::error_code{}, std::span<const_buffer>{}};
+
+            dest[0] = const_buffer(
+                buffer_.data() + consumed_,
+                buffer_.size() - consumed_);
+            co_return {std::error_code{}, dest.first(1)};
+        }
+
+        // Upstream exhausted?
+        if (exhausted_)
+            co_return {std::error_code{}, std::span<const_buffer>{}};
+
+        // Pull from upstream
+        buffer_.clear();
+        consumed_ = 0;
+
+        const_buffer upstream[8];  // const_buffer[8]
+        // ec: std::error_code, bufs: std::span<const_buffer>
+        auto [ec, bufs] = co_await source_->pull(upstream);
+
+        if (ec)
+            co_return {ec, std::span<const_buffer>{}};
+
+        if (bufs.empty())
+        {
+            exhausted_ = true;
+            co_return {std::error_code{}, std::span<const_buffer>{}};
+        }
+
+        // Transform: uppercase each byte
+        for (auto const& buf : bufs)  // const_buffer const&
+        {
+            auto const* data = static_cast<char const*>(buf.data());  // char const*
+            auto size = buf.size();  // std::size_t
+
+            for (std::size_t i = 0; i < size; ++i)
+            {
+                buffer_.push_back(static_cast<char>(
+                    std::toupper(static_cast<unsigned char>(data[i]))));
+            }
+        }
+
+        // Consume from upstream
+        source_->consume(buffer_size(bufs));
+
+        // Return transformed data
+        if (dest.empty() || buffer_.empty())
+            co_return {std::error_code{}, std::span<const_buffer>{}};
+
+        dest[0] = const_buffer(buffer_.data(), buffer_.size());
+        co_return {std::error_code{}, dest.first(1)};
+    }
+};
+
+// A transform that adds line numbers
+class line_numbering_transform
+{
+    any_buffer_source* source_;  // any_buffer_source*
+    std::string buffer_;         // std::string
+    std::size_t consumed_ = 0;   // std::size_t
+    std::size_t line_num_ = 1;   // std::size_t
+    bool at_line_start_ = true;  // bool
+    bool exhausted_ = false;     // bool
+
+public:
+    explicit line_numbering_transform(any_buffer_source& source)
+        : source_(&source)
+    {
+    }
+
+    void consume(std::size_t n) noexcept
+    {
+        consumed_ += n;
+        if (consumed_ >= buffer_.size())
+        {
+            buffer_.clear();
+            consumed_ = 0;
+        }
+    }
+
+    io_task<std::span<const_buffer>>
+    pull(std::span<const_buffer> dest)
+    {
+        if (consumed_ < buffer_.size())
+        {
+            if (dest.empty())
+                co_return {std::error_code{}, std::span<const_buffer>{}};
+
+            dest[0] = const_buffer(
+                buffer_.data() + consumed_,
+                buffer_.size() - consumed_);
+            co_return {std::error_code{}, dest.first(1)};
+        }
+
+        if (exhausted_)
+            co_return {std::error_code{}, std::span<const_buffer>{}};
+
+        buffer_.clear();
+        consumed_ = 0;
+
+        const_buffer upstream[8];  // const_buffer[8]
+        // ec: std::error_code, bufs: std::span<const_buffer>
+        auto [ec, bufs] = co_await source_->pull(upstream);
+
+        if (ec)
+            co_return {ec, std::span<const_buffer>{}};
+
+        if (bufs.empty())
+        {
+            exhausted_ = true;
+            co_return {std::error_code{}, std::span<const_buffer>{}};
+        }
+
+        // Transform: add line numbers
+        for (auto const& buf : bufs)  // const_buffer const&
+        {
+            auto const* data = static_cast<char const*>(buf.data());  // char const*
+            auto size = buf.size();  // std::size_t
+
+            for (std::size_t i = 0; i < size; ++i)
+            {
+                if (at_line_start_)
+                {
+                    buffer_ += std::to_string(line_num_++) + ": ";
+                    at_line_start_ = false;
+                }
+                buffer_ += data[i];
+                if (data[i] == '\n')
+                    at_line_start_ = true;
+            }
+        }
+
+        source_->consume(buffer_size(bufs));
+
+        if (dest.empty() || buffer_.empty())
+            co_return {std::error_code{}, std::span<const_buffer>{}};
+
+        dest[0] = const_buffer(buffer_.data(), buffer_.size());
+        co_return {std::error_code{}, dest.first(1)};
+    }
+};
+
+// Transfer from source to sink
+task<std::size_t> transfer(any_buffer_source& source, any_write_sink& sink)
+{
+    std::size_t total = 0;  // std::size_t
+    const_buffer bufs[8];   // const_buffer[8]
+
+    for (;;)
+    {
+        // ec: std::error_code, spans: std::span<const_buffer>
+        auto [ec, spans] = co_await source.pull(bufs);
+
+        if (ec)
+            throw std::system_error(ec);
+
+        if (spans.empty())
+            break;
+
+        for (auto const& buf : spans)  // const_buffer const&
+        {
+            // wec: std::error_code, n: std::size_t
+            auto [wec, n] = co_await sink.write(buf);
+            if (wec)
+                throw std::system_error(wec);
+            total += n;
+        }
+
+        source.consume(buffer_size(spans));
+    }
+
+    io_result<> eof_result = co_await sink.write_eof();
+    if (eof_result.ec)
+        throw std::system_error(eof_result.ec);
+
+    co_return total;
+}
+
+void demo_pipeline()
+{
+    std::cout << "=== Stream Pipeline Demo ===\n\n";
+
+    // Input data
+    std::string input = "hello world\nthis is a test\nof the pipeline\n";
+    std::cout << "Input:\n" << input << "\n";
+
+    // Create mock source with input data
+    test::fuse f;  // test::fuse
+    test::buffer_source source(f);  // test::buffer_source
+    source.provide(input);
+
+    // Build the pipeline using type-erased buffer sources.
+    // Using pointer construction (&source) for reference semantics -
+    // the wrapper does not take ownership, so source must outlive src.
+    any_buffer_source src{&source};  // any_buffer_source
+
+    uppercase_transform upper{src};  // uppercase_transform
+    any_buffer_source upper_src{&upper};  // any_buffer_source
+
+    line_numbering_transform numbered{upper_src};  // line_numbering_transform
+    any_buffer_source numbered_src{&numbered};  // any_buffer_source
+
+    // Create sink - pointer construction ensures sink outlives dst
+    test::write_sink sink(f);  // test::write_sink
+    any_write_sink dst{&sink};  // any_write_sink
+
+    // Run pipeline
+    std::size_t bytes = 0;  // std::size_t
+    test::run_blocking([&](std::size_t n) { bytes = n; })(
+        transfer(numbered_src, dst));
+
+    std::cout << "Output (" << bytes << " bytes):\n";
+    std::cout << sink.data() << "\n";
+}
+
+int main()
+{
+    try
+    {
+        demo_pipeline();
+    }
+    catch (std::system_error const& e)
+    {
+        std::cerr << "Pipeline error: " << e.what() << "\n";
+        return 1;
+    }
+    return 0;
+}
+
+
+
+
+
+

Build

+
+
+
+
add_executable(stream_pipeline stream_pipeline.cpp)
+target_link_libraries(stream_pipeline PRIVATE capy)
+
+
+
+
+
+

Walkthrough

+
+
+

Pipeline Structure

+
+
+
Source → Uppercase → LineNumbering → Sink
+
+
+
+

Data flows through the pipeline:

+
+
+
    +
  1. +

    Source provides raw input

    +
  2. +
  3. +

    Uppercase transforms to uppercase

    +
  4. +
  5. +

    LineNumbering adds line numbers

    +
  6. +
  7. +

    Sink collects output

    +
  8. +
+
+
+
+

BufferSource Implementation

+
+
+
io_task<std::span<const_buffer>>
+pull(std::span<const_buffer> dest)
+{
+    // Pull from upstream
+    // ec: std::error_code, bufs: std::span<const_buffer>
+    auto [ec, bufs] = co_await source_->pull(upstream);
+
+    // Transform data...
+
+    // Consume from upstream
+    source_->consume(buffer_size(bufs));
+
+    // Return transformed buffer
+    dest[0] = const_buffer(buffer_.data(), buffer_.size());
+    co_return {std::error_code{}, dest.first(1)};
+}
+
+
+
+

Each stage:

+
+
+
    +
  1. +

    Pulls buffers from upstream using co_await

    +
  2. +
  3. +

    Transforms the data

    +
  4. +
  5. +

    Calls consume() on upstream to indicate bytes processed

    +
  6. +
  7. +

    Returns transformed buffers

    +
  8. +
+
+
+
+

Type Erasure with Pointer Construction

+
+
+
// Using pointer construction (&source) for reference semantics
+any_buffer_source src{&source};  // any_buffer_source
+
+uppercase_transform upper{src};  // uppercase_transform
+any_buffer_source upper_src{&upper};  // any_buffer_source
+
+
+
+

any_buffer_source wraps each stage using pointer construction, allowing uniform composition while preserving the lifetime of the underlying objects.

+
+
+
+
+
+

Output

+
+
+
+
=== Stream Pipeline Demo ===
+
+Input:
+hello world
+this is a test
+of the pipeline
+
+Output (52 bytes):
+1: HELLO WORLD
+2: THIS IS A TEST
+3: OF THE PIPELINE
+
+
+
+
+
+

Exercises

+
+
+
    +
  1. +

    Add a compression/decompression stage

    +
  2. +
  3. +

    Implement a ROT13 transform

    +
  4. +
  5. +

    Create a filtering stage that drops lines matching a pattern

    +
  6. +
+
+
+
+
+

Summary

+
+
+

This example catalog demonstrated:

+
+
+
    +
  • +

    Basic task creation and launching

    +
  • +
  • +

    Coroutine synchronization with events

    +
  • +
  • +

    Buffer composition for scatter/gather I/O

    +
  • +
  • +

    Unit testing with mock streams

    +
  • +
  • +

    Compilation firewalls with type erasure

    +
  • +
  • +

    Cooperative cancellation with stop tokens

    +
  • +
  • +

    Concurrent execution with when_all

    +
  • +
  • +

    Custom buffer implementations

    +
  • +
  • +

    Real network I/O with Corosio

    +
  • +
  • +

    Data transformation pipelines

    +
  • +
+
+
+

These patterns form the foundation for building robust, efficient I/O applications with Capy.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8.intro.html b/preview/8.design/8.intro.html new file mode 100644 index 0000000..be9a947 --- /dev/null +++ b/preview/8.design/8.intro.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Design

+
+

Capy’s public interface—​tasks, buffers, streams—​is intentionally small. Behind that interface are design decisions that determine how concepts compose, where responsibility boundaries fall, and what guarantees the library can make. This section documents those decisions.

+
+
+

Each page examines one concept or facility in depth: its formal definition, the rationale behind its design, the alternatives that were considered, and the tradeoffs that were made. If you have ever wondered why a particular concept requires a specific primitive, or why certain abstractions exist as separate concepts, the answers are here. These documents are reference material for library contributors and advanced users. They assume familiarity with the tutorial sections and focus on design reasoning rather than usage.

+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8a.CapyLayering.html b/preview/8.design/8a.CapyLayering.html new file mode 100644 index 0000000..0adb7c0 --- /dev/null +++ b/preview/8.design/8a.CapyLayering.html @@ -0,0 +1,566 @@ + + + + + + + + + + + + + + Layered Abstractions :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Layered Abstractions

+
+
+
+

C++ async libraries have traditionally forced users into a single abstraction level, and every choice comes with baggage. You go with templates and you get zero overhead, full optimization, and unreadable error messages that scroll for pages. Compile times explode. You cannot hide implementation behind a compilation boundary, so you have no ABI stability. You go with virtual dispatch and you get readable code, stable ABIs, and a runtime cost that every call path pays whether it needs to or not.

+
+
+

This is a false binary. Users need different things at different layers of their system. A protocol parser needs zero-copy buffer access and zero overhead because it runs on every byte of every message. Business logic needs readability because the person maintaining it in two years needs to understand what it does. Library boundaries need ABI stability because you do not want downstream code recompiling every time an internal detail changes.

+
+
+

One abstraction level cannot serve all of these needs simultaneously. The insight behind Capy’s architecture is that users should choose the abstraction level appropriate to each part of their code, and the library should make that choice natural rather than painful.

+
+
+
+
+

The Three Layers

+
+
+

Capy offers three layers. They coexist. They interoperate. Users pick the one that matches their constraints.

+
+
+

The first layer is concepts. These are the template-based interfaces: ReadStream, WriteStream, BufferSink, BufferSource. Algorithms written against concepts get full optimization. The compiler sees through everything. There is no indirection, no vtable, no allocation overhead. This is what you use for hot inner loops, for protocol parsing, for any path where performance dominates:

+
+
+
+
template<BufferSource Src, WriteSink Sink>
+io_task<std::size_t>
+push_to(Src& source, Sink& sink);
+
+
+
+

The cost is that templates propagate. Every caller sees the full implementation. Compile times grow. You cannot hide this behind a .cpp file.

+
+
+

The second layer is type-erased wrappers. any_stream, any_read_stream, any_write_stream. These use a vtable internally, similar to std::function but specialized for I/O. You can write an algorithm against any_stream& and it compiles once, lives in a single translation unit, and works with any stream type:

+
+
+
+
task<> echo(any_stream& stream)
+{
+    char buf[1024];
+    for(;;)
+    {
+        auto [ec, n] = co_await stream.read_some(
+            mutable_buffer(buf));
+        if(ec.failed())
+            co_return;
+        co_await write(stream, const_buffer(buf, n));
+    }
+}
+
+
+
+

The cost is a virtual call per I/O operation. For operations dominated by syscalls and network latency, this cost is invisible. For tight loops over in-memory buffers, it matters.

+
+
+

The third layer is coroutine type erasure via task<>. This is the most powerful form of type erasure in the language. Inside a coroutine, when you write co_await, everything in the awaitable becomes type-erased from the perspective of the caller. The caller sees a task<>. The implementation is invisible. A pure virtual function returning task<> hides the stream type, the buffer strategy, the algorithm, the error handling - everything:

+
+
+
+
class connection_base {
+public:
+    task<> run();
+protected:
+    virtual task<> do_handshake() = 0;
+    virtual task<> do_shutdown() = 0;
+};
+
+
+
+

The SSL derived class performs a TLS handshake inside do_handshake(). The TCP derived class just connects. The base class implements all the shared business logic against an any_stream& and never knows what is underneath.

+
+
+

This is the layer you use for architectural boundaries. Plugin systems. Transport abstraction. Anything where you want complete separation between the interface and the implementation.

+
+
+
+
+

Compilation Boundary Economics

+
+
+

Benchmarks on Corosio gave us hard numbers on the cost of crossing a compilation boundary. The result is intuitive once you see it: the cost is proportional to the size of the coroutine.

+
+
+

For small, fast coroutines - the kind that do a quick buffer manipulation and return - the overhead of virtual dispatch plus parameter marshalling is a significant percentage of total execution time. For larger operations - data transfers dominated by syscalls, protocol handshakes, connection establishment - the boundary cost vanishes into noise.

+
+
+

This has a direct implication for how you structure code. Use concepts for tight inner operations where the work per call is small. Use type erasure at module boundaries where the work per call is large enough to absorb the overhead. The library does not make this decision for you. You make it based on your profiling data and your architecture requirements.

+
+
+

The user chooses where the boundary falls. Not the library.

+
+
+
+
+

Zero-Copy as a First-Class Concern

+
+
+

Buffer sink and buffer source invert the traditional ownership model. Instead of the caller allocating a buffer, filling it with data, and handing it to the library, the library exposes its own internal storage and the caller fills it in place. Zero copies. The data goes directly where it needs to be.

+
+
+

The BufferSink concept formalizes this with three operations. prepare() returns writable buffers from the sink’s internal storage. The caller writes data into those buffers. commit() tells the sink how many bytes were written:

+
+
+
+
concept BufferSink =
+    requires(T& sink, std::span<mutable_buffer> dest,
+             std::size_t n)
+    {
+        { sink.prepare(dest) }
+            -> std::same_as<std::span<mutable_buffer>>;
+        { sink.commit(n) } -> IoAwaitable;
+    };
+
+
+
+

This matters at the protocol level. The HTTP parser’s internal buffer is the buffer you write into. The serializer’s internal buffer is the buffer you read from. There is no intermediate copy between the network and the parser, and no intermediate copy between the serializer and the network.

+
+
+

The key detail is that commit() returns an IoAwaitable. When the sink is backed by a socket, commit() suspends and performs the actual write. When the sink is an in-memory buffer - a string, a parser, a test fixture - commit() completes synchronously without creating a coroutine frame. Same code, same API, no overhead for the synchronous case. This is what makes the buffer abstractions practical for both production I/O and testing.

+
+
+
+
+

Symmetric Transfer and the Pump

+
+
+

Symmetric transfer is the mechanism that allows Corosio to match or beat ASIO callback throughput. When one coroutine completes and its continuation is ready to run, symmetric transfer reuses the same coroutine frame without allocation and bypasses the global work queue entirely. ASIO callbacks always go through the queue. Symmetric transfer skips that step.

+
+
+

The pump mechanism extends this by allowing multiple inline completions before returning to the queue. If a chain of coroutines completes quickly, the pump lets them execute back-to-back without touching the scheduler. For throughput-sensitive workloads like HTTP servers, this is significant.

+
+
+

The trade-off is P99 latency. While the pump is running inline completions, queued work waits. For latency-sensitive workloads, you want to return to the queue more frequently so that every piece of work gets prompt attention. The pump is configurable. You can disable it entirely for HFT-style workloads that care about tail latency, or let it ramp up for servers that care about throughput.

+
+
+

The frame recycler is a per-thread cache of coroutine frames. Chain workloads that allocate and free frames in sequence benefit from this cache. Fan-out workloads that spawn many concurrent tasks can exhaust it. The right_now pattern addresses this for repeated invocations of the same operation: declare a stack object with a one-element frame cache, and repeated calls reuse that cache without touching the recycler at all. when_all could carry its own private frame cache sized to its arity, giving each child a frame from the parent’s stash via a TLS hook. Every use case that you make better can make another use case worse. You have to pay attention to that which is not seen.

+
+
+
+
+

The Type System as Architecture

+
+
+

The derived class pattern is the practical application of everything described above. A base class implements business logic against type-erased references. Derived classes carry concrete types and implement the operations that differ between transports.

+
+
+

Each derived class lives in its own translation unit. The linker only pulls in what is used. Users who need only TCP link only TCP code. Users who need SSL link the SSL translation unit. No variant that pulls in all transport code. No enum and switch that ties everything together. The type system enforces the separation:

+
+
+
+
// User who needs only plain TCP
+tcp_connection conn(ctx);
+
+// User who needs TLS
+ssl_connection conn(ctx, tls_context);
+
+// User who needs runtime transport selection
+multi_connection conn(ctx, config);
+
+
+
+

This extends naturally to testing. Derive a mock connection that uses Capy’s test stream with a fuse for error injection, and a mock timer for deterministic time control. The base class algorithm runs against the mock exactly as it would against a real connection. No conditional compilation, no test-only code paths in production logic, no #ifdef TESTING.

+
+
+

A database library built this way can express protocol parsing with zero-copy buffer sinks for the hot path, implement connection logic against type-erased streams for maintainability, let users select TCP vs. SSL vs. Unix at the type level for linker efficiency, and test without linking OpenSSL or running a real server. The hot paths use concepts. The cold paths use virtual dispatch. The architectural boundaries use task<>. Every user finds the abstraction level they need.

+
+
+
+
+

Choosing the Right Layer

+
+
+

The question that matters is: can a library author look at their problem and immediately see which layer to use? If the answer is yes, the design is working. If they have to think about it, something is wrong.

+
+
+

Protocol parsing: use BufferSink and BufferSource concepts as template parameters. Zero copy, zero overhead. Call member functions whose awaitables do all the work, with no coroutine frame allocation. The compiler optimizes everything.

+
+
+

Connection management: use concrete types like tcp_socket. These give you connect() and shutdown() - the operations that are transport-specific. But the concrete type is derived from io_stream, a class that models capy::Stream, so you can pass io_stream& to a non-template function for the business logic that sits on top of the connection.

+
+
+

Full transport abstraction across a library boundary: use any_stream. Complete type erasure, but you lose connection management - there is no connect() on an any_stream. This means you have to carefully arrange your code so it genuinely requires a physical separation in the Lakos sense. The protocol logic and the connection logic live in separate components, and the type-erased boundary sits between them.

+
+
+

The layers compose. An algorithm written against a BufferSource concept can be called from inside a coroutine that is type-erased behind a task<>, which is dispatched through a virtual function on a base class that holds an any_stream&. Each layer handles its part. Nothing leaks through the boundaries unless you want it to.

+
+
+

This is what it means when we say the user chooses. Capy provides the tools. The user decides where the boundaries go based on what they know about their performance requirements, their compilation budget, and their architecture. The library does not impose a single answer because there is not one.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8b.Separation.html b/preview/8.design/8b.Separation.html new file mode 100644 index 0000000..d569086 --- /dev/null +++ b/preview/8.design/8b.Separation.html @@ -0,0 +1,661 @@ + + + + + + + + + + + + + + Why Capy Is Separate :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Why Capy Is Separate

+
+
+
+

"Why are Capy and Corosio two separate libraries? Why not just put everything in one place?"

+
+
+

The answer is physical design. Capy and Corosio sit at different levels of the physical hierarchy. They encapsulate different information, change for different reasons, and have different platform dependencies. Merging them would degrade the design along every axis that matters for a large-scale system: testability, reusability, and build cost.

+
+
+

This document applies well-established physical design principles to show why the separation is a structural requirement.

+
+
+
+
+

What Lives Where

+
+
+

Capy provides the foundational abstractions for coroutine-based I/O. Tasks. Buffers. Stream concepts. Executors. The IoAwaitable protocol. Type-erased streams. Composition primitives like when_all and when_any. It is pure C++20. It does not include a single line of platform-specific code. No sockets. No file descriptors. No #ifdef _WIN32.

+
+
+

Corosio provides platform networking. TCP sockets. TLS streams. DNS resolution. Timers. Signal handling. It implements four platform-specific event loop backends: IOCP on Windows, epoll on Linux, kqueue on macOS/BSD, and POSIX select as a fallback. Corosio depends on Capy. Capy does not depend on Corosio.

+
+
+

The dependency arrow points in one direction. That is not an accident.

+
+
+
+
+

Levelization

+
+
+

Three principles underpin the physical organization of large systems:

+
+
+
    +
  1. +

    Fine-grained encapsulation (Parnas, 1972)

    +
  2. +
  3. +

    Acyclic physical dependencies (Dijkstra, 1968)

    +
  4. +
  5. +

    Well-documented internal interface boundaries (Myers, 1978)

    +
  6. +
+
+
+

Lakos synthesized these into a discipline called levelization. The idea is not a means of achieving fine-grained components. It is a means of organizing the implied dependencies of the logical entities in a system so that the component dependencies are acyclic (see Fig 0-15, p. 22 of Lakos'20).

+
+
+

The levels are straightforward:

+
+
+
    +
  • +

    A component that depends on nothing is level 0.

    +
  • +
  • +

    A component that depends only on level-0 components is level 1.

    +
  • +
  • +

    A component that depends on level-1 components is level 2.

    +
  • +
  • +

    And so on.

    +
  • +
+
+
+

This creates a directed acyclic graph where dependencies flow in one direction. If the graph has a cycle, the design is broken. The presence of acyclic dependencies does not guarantee good design, but the presence of cycles guarantees bad design.

+
+
+
+
+

Systems with [acyclic] physical hierarchies are fundamentally +easier and more economical to maintain, test, and reuse than +tightly interdependent systems.

+
+
+
+— John Lakos
+Large-Scale C++ Software Design (1996) +
+
+
+

Knowing that logical designs must be levelized, you alter the logical designs accordingly. This is the insight that separates engineers who have built at scale from those who have not.

+
+
+

Capy sits at a lower level. It provides tasks, buffers, stream concepts, and executors - abstractions that do not depend on any particular I/O backend. Corosio sits at a higher level. It provides sockets, TLS, and event loops that depend on Capy’s abstractions.

+
+
+

Components at different levels belong in different packages. This is a structural requirement, not a style preference.

+
+
+
+
+

Cumulative Component Dependency

+
+
+

Lakos quantified the cost of getting levels wrong with Cumulative Component Dependency (CCD): the sum over all components in a subsystem of the number of components needed in order to test each component incrementally (see Figure 4-22, p. 191 of Lakos'96).

+
+
+

CCD ranges from N for a perfectly horizontal (flat) design to N-squared for a vertical or cyclically dependent one. The metric is additive for independent subsystems. If two independent libraries each have CCD of 5, combining them without adding cross-dependencies gives CCD 10 - exactly the sum:

+
+
+
+
--------    ----------
+   [3]         [3]
+   / \         / \
+[1]  [1]    [1]   [1]
+--------    ---------
+CCD = 5      CCD = 5
+
+ -------------------
+    [3]       [3]
+    / \       / \
+ [1]   [1] [1]   [1]
+ -------------------
+      CCD = 10
+
+
+
+

Each component should have a single purpose. Ideally all of the functionality within a component is primitive - if you can write a function in terms of a type rather than as a member of that type, write a free function (or today, a template function constrained by a concept). This keeps levels flat and CCD low.

+
+
+

Merging two libraries at different levels inflates CCD. Every component that only needs buffers and tasks now drags in sockets, TLS, and four platform backends. Testing cost, build cost, and cognitive cost all increase.

+
+
+
+
+

Deep Modules

+
+
+

Ousterhout’s model for module quality measures interface area against implementation depth. A deep module has a small interface and a large implementation.

+
+
+
+
+

The best modules are those that provide powerful functionality, +but have a simple interface.

+
+
+
+— John Ousterhout
+A Philosophy of Software Design (2021) +
+
+
+

Capy is a deep module. Its public surface is narrow: a handful of concepts (ReadStream, WriteStream, BufferSource, BufferSink), a task type, an executor model, and buffer utilities. Behind that surface lives a substantial implementation: coroutine frame allocation, forward propagation of executors and stop tokens, type-erased stream machinery, and composition primitives.

+
+
+

Corosio is also a deep module, but a different one. It hides platform-specific event loop complexity (IOCP, epoll, kqueue, select) behind a uniform socket and timer interface.

+
+
+

These two modules hide different information. That is the practical reason they are separate. Lakos would say: do not collocate two independent systems, because doing so creates gratuitous physical dependencies. Ousterhout would say: modules that hide different information should remain different modules.

+
+
+

Capy pulls the complexity of coroutine execution, buffer management, and context propagation downward, so that libraries like Http and Corosio do not have to deal with it. Merging Capy into Corosio does not eliminate that complexity. It buries it inside a larger library where it is harder to find, harder to test, and impossible to reuse without taking the whole thing.

+
+
+
+
+

Writing Against the Narrowest Interface

+
+
+

A ReadStream concept captures the essential operation: anything you can read_some from. TCP sockets, TLS streams, file handles, in-memory buffers - one generic algorithm works with all of them. That algorithm belongs in Capy, not Corosio, because it depends only on the concept, not on any particular implementation.

+
+
+

Stepanov’s principle applies here: algorithms should be abstracted away from particular implementations so that the minimum requirements the algorithm assumes are the only requirements the code uses. In practice, zero-overhead abstraction is an ideal rather than a guarantee - Chandler Carruth has argued persuasively that real compilers on real hardware rarely achieve it perfectly. But the principle of coding against minimal requirements remains sound, even when the abstraction has some cost.

+
+
+

If you can express your algorithm using Capy instead of Corosio, you depend on fewer things. Fewer dependencies means lower CCD, easier testing, and broader reuse.

+
+
+
+
+

The Existence Proof

+
+
+

Boost.Http is a sans-I/O HTTP/1.1 protocol library. It parses requests, serializes responses, and implements routing. It is written entirely against Capy. It has zero dependency on Corosio.

+
+
+

This is not a hypothetical. It is a real library, shipping today. It works with any I/O backend that satisfies Capy’s stream concepts. You could plug in Corosio’s TCP sockets, or Asio’s sockets, or a mock stream for testing. The protocol logic does not care.

+
+
+

If Capy were merged into Corosio, Boost.Http would be forced to depend on platform networking it never touches. Every user who wants to parse HTTP headers would need to link against IOCP on Windows, epoll on Linux, and kqueue on macOS. The HTTP parser does not use sockets. It should not pay for sockets.

+
+
+

This is precisely the excessive link-time dependency that levelization is designed to prevent. Merging Capy into Corosio does not create a cycle, but it forces every consumer of Capy’s abstractions to inherit Corosio’s platform dependencies. The cost is paid by everyone, even those who need nothing from Corosio.

+
+
+
+
+

Testing in Isolation

+
+
+

With Capy as a separate library, you can test buffer algorithms, stream concepts, and task machinery without a network stack. No sockets. No event loops. No platform dependencies. Just pure C++20 coroutine logic.

+
+
+

With Corosio as a separate library, you can test socket behavior, DNS resolution, and timer accuracy against a known-good Capy foundation.

+
+
+

Merge them, and every test of a buffer copy routine must compile against platform I/O headers. Every CI run must configure platform-specific backends even to test portable abstractions. The test matrix explodes. Each unnecessary dependency is small, but they accumulate, and once they accumulate they are nearly impossible to remove.

+
+
+
+
+

Platform Isolation

+
+
+

Capy is portable C++20. It compiles on any conforming compiler with no platform-specific code. It can be used on embedded systems, in WebAssembly, on platforms that do not have sockets, and in environments where the I/O backend has not been written yet.

+
+
+

Corosio contains four platform backends, each a substantial body of platform-specific code:

+
+
+
    +
  • +

    IOCP on Windows (sockets, overlapped I/O, NT timers)

    +
  • +
  • +

    epoll on Linux

    +
  • +
  • +

    kqueue on macOS and BSD

    +
  • +
  • +

    select as a POSIX fallback

    +
  • +
+
+
+

Merging these into Capy would mean that a developer who wants a task<> type or a circular_dynamic_buffer must compile against platform I/O headers. Keeping Capy separate ensures that none of the headers a consumer includes transitively pull in anything from the platform I/O layer. Consumers take only what they need.

+
+
+
+
+

Conclusion

+
+
+

Good design separates things that change for different reasons. Capy changes when the coroutine execution model evolves - new composition primitives, new buffer types, refinements to the IoAwaitable protocol. Corosio changes when platform I/O APIs evolve - new io_uring features on Linux, new IOCP capabilities on Windows, new TLS backends.

+
+
+

The converse is also important: things that change together should not be separated. An unstable implementation detail that serves only one component belongs inside that component, not in a separate library. Capy and Corosio do not change together. They have different rates of change, different levels of abstraction, and different platform dependencies.

+
+
+

These are distinct reasons for separation. Levelization demands acyclic dependencies between packages. Isolation prevents excessive compile-time and link-time coupling. Abstraction - hiding unnecessary details - reduces the interface each consumer must understand. The three reinforce each other, but they are separate concerns.

+
+
+

Capy is the narrow waist. It is the small-surface-area interface that hides substantial machinery. It is the lower-level foundation that everything else builds on. Merging it into Corosio would force every consumer of portable abstractions to pay for platform networking they do not use.

+
+
+

Keep them separate. The architecture demands it.

+
+
+
+
+

References

+
+
+
    +
  1. +

    John Lakos. Large-Scale C++ Software Design. Addison-Wesley, 1996.

    +
  2. +
  3. +

    John Lakos. Large-Scale C++, Volume I: Process and Architecture. Addison-Wesley, 2020.

    +
  4. +
  5. +

    John Ousterhout. A Philosophy of Software Design. Yaknyam Press, 2nd Edition, 2021.

    +
  6. +
  7. +

    Alexander Stepanov. "Al Stevens Interviews Alex Stepanov." Dr. Dobb’s Journal, 1995.

    +
  8. +
  9. +

    D.L. Parnas. "On the Criteria To Be Used in Decomposing Systems into Modules." Communications of the ACM, 1972.

    +
  10. +
  11. +

    E.W. Dijkstra. "The Structure of the 'THE'-Multiprogramming System." Communications of the ACM, 1968.

    +
  12. +
  13. +

    G.J. Myers. Composite/Structured Design. Van Nostrand Reinhold, 1978.

    +
  14. +
+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8c.ReadStream.html b/preview/8.design/8c.ReadStream.html new file mode 100644 index 0000000..14c68a2 --- /dev/null +++ b/preview/8.design/8c.ReadStream.html @@ -0,0 +1,915 @@ + + + + + + + + + + + + + + ReadStream Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

ReadStream Concept Design

+
+

Overview

+
+
+

This document describes the design of the ReadStream concept: the fundamental partial-read primitive in the concept hierarchy. It explains why read_some is the correct building block, how composed algorithms build on top of it, and the relationship to ReadSource.

+
+
+
+
+

Definition

+
+
+
+
template<typename T>
+concept ReadStream =
+    requires(T& stream, mutable_buffer_archetype buffers)
+    {
+        { stream.read_some(buffers) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(stream.read_some(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+

A ReadStream provides a single operation:

+
+
+

read_some(buffers) — Partial Read

+
+

Reads one or more bytes from the stream into the buffer sequence. Returns (error_code, std::size_t) where n is the number of bytes read.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n >= 1 and n <= buffer_size(buffers).

    +
  • +
  • +

    On EOF: ec == cond::eof, n == 0.

    +
  • +
  • +

    On error: ec, n == 0.

    +
  • +
  • +

    If buffer_empty(buffers): completes immediately, !ec, n == 0.

    +
  • +
+
+
+

The caller must not assume the buffer is filled. read_some may return fewer bytes than the buffer can hold. This is the defining property of a partial-read primitive.

+
+
+

Once read_some returns an error (including EOF), the caller must not call read_some again. The stream is done. Not all implementations can reproduce a prior error on subsequent calls, so the behavior after an error is undefined.

+
+
+

Buffers in the sequence are filled completely before proceeding to the next buffer in the sequence.

+
+
+
+

Buffer Lifetime

+
+

The caller must ensure that the memory referenced by buffers remains valid until the co_await expression returns.

+
+
+
+

Conforming Signatures

+
+
+
template<MutableBufferSequence Buffers>
+IoAwaitable auto read_some(Buffers buffers);
+
+
+
+

Buffer sequences should be accepted by value when the member function is a coroutine, to ensure the sequence lives in the coroutine frame across suspension points.

+
+
+
+
+
+
+

Concept Hierarchy

+
+
+

ReadStream is the base of the read-side hierarchy:

+
+
+
+
ReadStream    { read_some }
+    |
+    v
+ReadSource    { read_some, read }
+
+
+
+

ReadSource refines ReadStream. Every ReadSource is a ReadStream. Algorithms constrained on ReadStream accept both raw streams and sources. The ReadSource concept adds a complete-read primitive on top of the partial-read primitive.

+
+
+

This mirrors the write side:

+
+
+
+
WriteStream   { write_some }
+    |
+    v
+WriteSink     { write_some, write, write_eof(buffers), write_eof() }
+
+
+
+
+
+

Composed Algorithms

+
+
+

Three composed algorithms build on read_some:

+
+
+

read(stream, buffers) — Fill a Buffer Sequence

+
+
+
auto read(ReadStream auto& stream,
+          MutableBufferSequence auto const& buffers)
+    -> io_task<std::size_t>;
+
+
+
+

Loops read_some until the entire buffer sequence is filled or an error (including EOF) occurs. On success, n == buffer_size(buffers).

+
+
+
+
template<ReadStream Stream>
+task<> read_header(Stream& stream)
+{
+    char header[16];
+    auto [ec, n] = co_await read(
+        stream, mutable_buffer(header));
+    if(ec == cond::eof)
+        co_return;  // clean shutdown
+    if(ec)
+        co_return;
+    // header contains exactly 16 bytes
+}
+
+
+
+
+

read(stream, dynamic_buffer) — Read Until EOF

+
+
+
auto read(ReadStream auto& stream,
+          DynamicBufferParam auto&& buffers,
+          std::size_t initial_amount = 2048)
+    -> io_task<std::size_t>;
+
+
+
+

Reads from the stream into a dynamic buffer until EOF is reached. The buffer grows with a 1.5x factor when filled. On success (EOF), ec is clear and n is the total bytes read.

+
+
+
+
template<ReadStream Stream>
+task<std::string> slurp(Stream& stream)
+{
+    std::string body;
+    auto [ec, n] = co_await read(
+        stream, string_dynamic_buffer(&body));
+    if(ec)
+        co_return {};
+    co_return body;
+}
+
+
+
+
+

read_until(stream, dynamic_buffer, match) — Delimited Read

+
+

Reads from the stream into a dynamic buffer until a delimiter or match condition is found. Used for line-oriented protocols and message framing.

+
+
+
+
template<ReadStream Stream>
+task<> read_line(Stream& stream)
+{
+    std::string line;
+    auto [ec, n] = co_await read_until(
+        stream, string_dynamic_buffer(&line), "\r\n");
+    if(ec)
+        co_return;
+    // line contains data up to and including "\r\n"
+}
+
+
+
+
+
+
+

Use Cases

+
+
+

Incremental Processing with read_some

+
+

When processing data as it arrives without waiting for a full buffer, read_some is the right choice. This is common for real-time data or when the processing can handle partial input.

+
+
+
+
template<ReadStream Stream>
+task<> echo(Stream& stream, WriteStream auto& dest)
+{
+    char buf[4096];
+    for(;;)
+    {
+        auto [ec, n] = co_await stream.read_some(
+            mutable_buffer(buf));
+        if(ec == cond::eof)
+            co_return;
+        if(ec)
+            co_return;
+
+        // Forward whatever we received immediately
+        auto [wec, nw] = co_await dest.write_some(
+            const_buffer(buf, n));
+        if(wec)
+            co_return;
+    }
+}
+
+
+
+
+

Relaying from ReadStream to WriteStream

+
+

When relaying data from a reader to a writer, read_some feeds write_some directly. This is the fundamental streaming pattern.

+
+
+
+
template<ReadStream Src, WriteStream Dest>
+task<> relay(Src& src, Dest& dest)
+{
+    char storage[65536];
+    circular_dynamic_buffer cb(storage, sizeof(storage));
+
+    for(;;)
+    {
+        // Read into free space
+        auto mb = cb.prepare(cb.capacity());
+        auto [rec, nr] = co_await src.read_some(mb);
+        cb.commit(nr);
+
+        if(rec && rec != cond::eof)
+            co_return;
+
+        // Drain to destination
+        while(cb.size() > 0)
+        {
+            auto [wec, nw] = co_await dest.write_some(
+                cb.data());
+            if(wec)
+                co_return;
+            cb.consume(nw);
+        }
+
+        if(rec == cond::eof)
+            co_return;
+    }
+}
+
+
+
+

Because ReadSource refines ReadStream, this relay function also accepts ReadSource types. An HTTP body source or a decompressor can be relayed to a WriteStream using the same function.

+
+
+
+
+
+

Relationship to the Write Side

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
Read SideWrite Side

ReadStream::read_some

WriteStream::write_some

read free function (composed)

write_now (composed, eager)

read_until (composed, delimited)

No write-side equivalent

ReadSource::read

WriteSink::write

+
+
+
+

Design Foundations: Why Errors Exclude Data

+
+
+

The read_some contract requires that n is 0 whenever ec is set. Data and errors are mutually exclusive outcomes. This is the most consequential design decision in the ReadStream concept, with implications for every consumer of read_some in the library. The rule follows Asio’s established AsyncReadStream contract, is reinforced by the behavior of POSIX and Windows I/O system calls, and produces cleaner consumer code. This section explains the design and its consequences.

+
+
+

Reconstructing Kohlhoff’s Reasoning

+
+

Christopher Kohlhoff’s Asio library defines an AsyncReadStream concept with the identical requirement: on error, bytes_transferred is 0. No design rationale document accompanies this rule. The reasoning presented here was reconstructed from three sources:

+
+
+
    +
  • +

    The Asio source code. The function non_blocking_recv1 in socket_ops.ipp explicitly sets bytes_transferred = 0 on every error path. The function complete_iocp_recv maps Windows IOCP errors to portable error codes, relying on the operating system’s guarantee that failed completions report zero bytes. These are deliberate choices, not accidental pass-through of OS behavior.

    +
  • +
  • +

    A documentation note Kohlhoff left. Titled "Why EOF is an error," it gives two reasons: composed operations need EOF-as-error to report contract violations, and EOF-as-error disambiguates the end of a stream from a successful zero-byte read. The note is terse but the implications are deep.

    +
  • +
  • +

    Analysis of the underlying system calls. POSIX recv() and Windows WSARecv() both enforce a binary outcome per call: data or error, never both. This is not because the C++ abstraction copied the OS, but because both levels face the same fundamental constraint.

    +
  • +
+
+
+

The following sections examine each of these points and their consequences.

+
+
+
+

Alignment with Asio

+
+

Asio’s AsyncReadStream concept has enforced the same rule for over two decades: on error, bytes_transferred is 0. This is a deliberate design choice, not an accident. The Asio source code explicitly zeroes bytes_transferred on every error path, and the underlying system calls (POSIX recv(), Windows IOCP) enforce binary outcomes at the OS level. The read_some contract follows this established practice.

+
+
+
+

The Empty-Buffer Rule

+
+

Every ReadStream must support the following:

+
+
+
+read_some(empty_buffer) completes immediately with {success, 0}. +
+
+
+

This is a no-op. The caller passed no buffer space, so no I/O is attempted. The operation does not inspect the stream’s internal state because that would require a probe capability — a way to ask "is there data? is the stream at EOF?" — without actually reading. Not every source supports probing. A TCP socket does not know that its peer has closed until it calls recv() and gets 0 back. A pipe does not know it is broken until a read fails. The empty-buffer rule is therefore unconditional: return {success, 0} regardless of the stream’s state.

+
+
+

This rule is a natural consequence of the contract, not a proof of it. When no I/O is attempted, no state is discovered and no error is reported.

+
+
+
+

Why EOF Is an Error

+
+

Kohlhoff’s documentation note gives two reasons for making EOF an error code rather than a success:

+
+
+

Composed operations need EOF-as-error to report contract violations. The composed read(stream, buffer(buf, 100)) promises to fill exactly 100 bytes. If the stream ends after 50, the operation did not fulfill its contract. Reporting {success, 50} would be misleading — it suggests the operation completed normally. Reporting {eof, 50} tells the caller both what happened (50 bytes landed in the buffer) and why the operation stopped (the stream ended). EOF-as-error is the mechanism by which composed operations explain early termination.

+
+
+

EOF-as-error disambiguates the empty-buffer no-op from the end of a stream. Without EOF-as-error, both read_some(empty_buffer) on a live stream and read_some(non_empty_buffer) on an exhausted stream would produce {success, 0}. The caller could not distinguish "I passed no buffer" from "the stream is done." Making EOF an error code separates these two cases cleanly.

+
+
+

These two reasons reinforce each other. Composed operations need EOF to be an error code so they can report early termination. The empty-buffer rule needs EOF to be an error code so {success, 0} is unambiguously a no-op. Together with the rule that errors exclude data, read_some results form a clean trichotomy: success with data, or an error (including EOF) without data.

+
+
+
+

The Write-Side Asymmetry

+
+

On the write side, WriteSink provides write_eof(buffers) to atomically combine the final data with the EOF signal. A natural question follows: if the write side fuses data with EOF, why does the read side forbid it?

+
+
+

The answer is that the two sides of the I/O boundary have different roles. The writer decides when to signal EOF. The reader discovers it. This asymmetry has three consequences:

+
+
+

write_eof exists for correctness, not convenience. Protocol framings require the final data and the EOF marker to be emitted together so the peer observes a complete message. HTTP chunked encoding needs the terminal 0\r\n\r\n coalesced with the final data chunk. A TLS session needs the close-notify alert coalesced with the final application data. A compressor needs Z_FINISH applied to the final input. These are correctness requirements, not optimizations. On the read side, whether the last bytes arrive with EOF or on a separate call does not change what the reader observes. The data and the order are identical either way.

+
+
+

write_eof is a separate function the caller explicitly invokes. write_some never signals EOF. The writer opts into data-plus-EOF by calling a different function. The call site reads write_eof(data) and the intent is unambiguous. If read_some could return data with EOF, every call to read_some would sometimes be a data-only operation and sometimes a data-plus-EOF operation. The stream decides which mode the caller gets, at runtime. Every call site must handle both possibilities. The burden falls on every consumer in the codebase, not on a single call site that opted into the combined behavior.

+
+
+

A hypothetical read_eof makes no sense. On the write side, write_eof exists because the producer signals the end of data. On the read side, the consumer does not tell the stream to end — it discovers that the stream has ended. EOF flows from producer to consumer, not the reverse. There is no action the reader can take to "read the EOF." The reader discovers EOF as a side effect of attempting to read.

+
+
+
+

A Clean Trichotomy

+
+

With the current contract, every read_some result falls into exactly one of three mutually exclusive cases:

+
+
+
    +
  • +

    Success: !ec, n >= 1 — data arrived, process it.

    +
  • +
  • +

    EOF: ec == cond::eof, n == 0 — stream ended, no data.

    +
  • +
  • +

    Error: ec, n == 0 — failure, no data.

    +
  • +
+
+
+

Data is present if and only if the operation succeeded. This invariant — data implies success — eliminates an entire category of reasoning from every read loop. The common pattern is:

+
+
+
+
auto [ec, n] = co_await stream.read_some(buf);
+if(ec)
+    break;        // EOF or error -- no data to handle
+process(buf, n);  // only reached on success, n >= 1
+
+
+
+

If read_some could return n > 0 with EOF, the loop becomes:

+
+
+
+
auto [ec, n] = co_await stream.read_some(buf);
+if(n > 0)
+    process(buf, n);  // must handle data even on EOF
+if(ec)
+    break;
+
+
+
+

Every consumer pays this tax: an extra branch to handle data accompanying EOF. The branch is easy to forget. Forgetting it silently drops the final bytes of the stream — a bug that only manifests when the source delivers EOF with its last data rather than on a separate call. A TCP socket receiving data in one packet and FIN in another will not trigger the bug. A memory source that knows its remaining length will. The non-determinism makes the bug difficult to reproduce and diagnose.

+
+
+

The clean trichotomy eliminates this class of bugs entirely.

+
+
+
+

Conforming Sources

+
+

Every concrete ReadStream implementation naturally separates its last data delivery from its EOF signal:

+
+
+
    +
  • +

    TCP sockets: read_some maps to a single recv() or WSARecv() call, returning whatever the kernel has buffered. The kernel delivers bytes on one call and returns 0 on the next. The separation is inherent in the POSIX and Windows APIs.

    +
  • +
  • +

    TLS streams: read_some decrypts and returns one TLS record’s worth of application data. The close-notify alert arrives as a separate record.

    +
  • +
  • +

    HTTP content-length body: the source delivers bytes up to the content-length limit. Once the limit is reached, the next read_some returns EOF.

    +
  • +
  • +

    HTTP chunked body: the unchunker delivers decoded data from chunks. The terminal 0\r\n\r\n is parsed on a separate pass that returns EOF.

    +
  • +
  • +

    Compression (inflate): the decompressor delivers output bytes. When Z_STREAM_END is detected, the next read returns EOF.

    +
  • +
  • +

    Memory source: returns min(requested, remaining) bytes. When remaining reaches 0, the next call returns EOF.

    +
  • +
  • +

    QUIC streams: read_some returns data from received QUIC frames. Stream FIN is delivered as EOF on a subsequent call.

    +
  • +
  • +

    Buffered read streams: read_some returns data from an internal buffer, refilling from the underlying stream when empty. EOF propagates from the underlying stream.

    +
  • +
  • +

    Test mock streams: read_some returns configurable data and error sequences for testing.

    +
  • +
+
+
+

No source is forced into an unnatural pattern. The read_some call that discovers EOF is the natural result of attempting to read from an exhausted stream — not a separate probing step. Once the caller receives EOF, it stops reading.

+
+
+
+

Composed Operations and Partial Results

+
+

The composed read algorithm (and ReadSource::read) does report n > 0 on EOF, because it accumulates data across multiple internal read_some calls. When the underlying stream signals EOF mid-accumulation, discarding the bytes already gathered would be wrong. The caller needs n to know how much valid data landed in the buffer.

+
+
+

The design separates concerns cleanly: the single-shot primitive (read_some) delivers unambiguous results with a clean trichotomy. Composed operations that accumulate state (read) report what they accumulated, including partial results on EOF. Callers who need partial-on-EOF semantics get them through the composed layer, while the primitive layer remains clean.

+
+
+
+

Evidence from the Asio Implementation

+
+

The Asio source code confirms this design at every level.

+
+
+

On POSIX platforms, non_blocking_recv1 in socket_ops.ipp calls recv() and branches on the result. If recv() returns a positive value, the bytes are reported as a successful transfer. If recv() returns 0 on a stream socket, EOF is reported. If recv() returns -1, the function explicitly sets bytes_transferred = 0 before returning the error. The POSIX recv() system call itself enforces binary outcomes: it returns N > 0 on success, 0 on EOF, or -1 on error. A single call never returns both data and an error.

+
+
+

On Windows, complete_iocp_recv processes the results from GetQueuedCompletionStatus. It maps ERROR_NETNAME_DELETED to connection_reset and ERROR_PORT_UNREACHABLE to connection_refused. Windows IOCP similarly reports zero bytes_transferred on failed completions. The operating system enforces the same binary outcome per I/O completion.

+
+
+

The one edge case is POSIX signal interruption (EINTR). If a signal arrives after recv() has already copied some bytes, the kernel returns the partial byte count as success rather than -1/EINTR. Asio handles this transparently by retrying on EINTR, so the caller never observes it. Even the kernel does not combine data with an error — it chooses to report the partial data as success.

+
+
+
+

Convergent Design with POSIX

+
+

POSIX recv() independently enforces the same rule: N > 0 on success, -1 on error, 0 on EOF. The kernel never returns "here are your last 5 bytes, and also EOF." It delivers the available bytes on one call and returns 0 on the next. This is not because the C++ abstraction copied POSIX semantics. It is because the kernel faces the same fundamental constraint: state is discovered through the act of I/O. The alignment between read_some and recv() is convergent design, not leaky abstraction.

+
+
+
+
+
+

Summary

+
+
+

ReadStream provides read_some as the single partial-read primitive. This is deliberately minimal:

+
+
+
    +
  • +

    Algorithms that need to fill a buffer completely use the read composed algorithm.

    +
  • +
  • +

    Algorithms that need delimited reads use read_until.

    +
  • +
  • +

    Algorithms that need to process data as it arrives use read_some directly.

    +
  • +
  • +

    ReadSource refines ReadStream by adding read for complete-read semantics.

    +
  • +
+
+
+

The contract that errors exclude data follows Asio’s established AsyncReadStream contract, aligns with POSIX and Windows system call semantics, and produces a clean trichotomy that makes every read loop safe by construction.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8d.ReadSource.html b/preview/8.design/8d.ReadSource.html new file mode 100644 index 0000000..9c1cc72 --- /dev/null +++ b/preview/8.design/8d.ReadSource.html @@ -0,0 +1,936 @@ + + + + + + + + + + + + + + ReadSource Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

ReadSource Concept Design

+
+

Overview

+
+
+

This document describes the design of the ReadSource concept: a refinement of ReadStream that adds a complete-read primitive. It explains how ReadSource relates to ReadStream, why the refinement hierarchy mirrors the write side, and the use cases each serves.

+
+
+
+
+

Definition

+
+
+
+
template<typename T>
+concept ReadSource =
+    ReadStream<T> &&
+    requires(T& source, mutable_buffer_archetype buffers)
+    {
+        { source.read(buffers) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(source.read(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+

ReadSource refines ReadStream. Every ReadSource is a ReadStream. A ReadSource provides two operations:

+
+
+

read_some(buffers) — Partial Read (inherited from ReadStream)

+
+

Reads one or more bytes from the source into the buffer sequence. Returns (error_code, std::size_t) where n is the number of bytes read. May return fewer bytes than the buffer can hold.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n >= 1 and n <= buffer_size(buffers).

    +
  • +
  • +

    On EOF: ec == cond::eof, n == 0.

    +
  • +
  • +

    On error: ec, n == 0.

    +
  • +
  • +

    If buffer_empty(buffers): completes immediately, !ec, n == 0.

    +
  • +
+
+
+

Once read_some returns an error (including EOF), the caller must not call read_some again. The stream is done. Not all implementations can reproduce a prior error on subsequent calls, so the behavior after an error is undefined.

+
+
+
+
+

read(buffers) — Complete Read

+
+

Reads data into the buffer sequence. Either fills the entire buffer or returns an error. Returns (error_code, std::size_t) where n is the number of bytes read.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n == buffer_size(buffers). The buffer is completely filled.

    +
  • +
  • +

    On EOF: ec == cond::eof, n is the number of bytes read before EOF was reached (may be less than buffer_size(buffers)).

    +
  • +
  • +

    On error: ec, n is the number of bytes read before the error.

    +
  • +
  • +

    If buffer_empty(buffers): completes immediately, !ec, n == 0.

    +
  • +
+
+
+

Successful partial reads are not permitted. Either the entire buffer is filled, or the operation returns with an error. This is the defining property of a complete-read primitive.

+
+
+

Once read returns an error (including EOF), the caller must not call read or read_some again. The source is done. Not all implementations can reproduce a prior error on subsequent calls, so the behavior after an error is undefined.

+
+
+

When the buffer sequence contains multiple buffers, each buffer is filled completely before proceeding to the next.

+
+
+
+

Buffer Lifetime

+
+

The caller must ensure that the memory referenced by buffers remains valid until the co_await expression returns.

+
+
+
+

Conforming Signatures

+
+
+
template<MutableBufferSequence Buffers>
+IoAwaitable auto read_some(Buffers buffers);
+
+template<MutableBufferSequence Buffers>
+IoAwaitable auto read(Buffers buffers);
+
+
+
+
+
+
+
+

Concept Hierarchy

+
+
+
+
ReadStream    { read_some }
+    |
+    v
+ReadSource    { read_some, read }
+
+
+
+

This mirrors the write side:

+
+
+
+
WriteStream   { write_some }
+    |
+    v
+WriteSink     { write_some, write, write_eof(buffers), write_eof() }
+
+
+
+

Algorithms constrained on ReadStream accept both raw streams and sources. Algorithms that need the complete-read guarantee constrain on ReadSource.

+
+
+
+
+

Why ReadSource Refines ReadStream

+
+
+

Every concrete ReadSource type has a natural read_some:

+
+
+
    +
  • +

    HTTP content-length body: read_some returns min(available_from_network, remaining_content_length) bytes. It is the underlying stream’s read_some capped by the body’s limit.

    +
  • +
  • +

    HTTP chunked body: read_some delivers whatever unchunked data is available from the current chunk.

    +
  • +
  • +

    Decompression source (inflate, zstd): read_some does one decompression pass — feeds available compressed input to the decompressor and returns whatever output is produced. This is how zlib::inflate() naturally works.

    +
  • +
  • +

    File source: read_some is a single read() syscall. It is the OS primitive.

    +
  • +
  • +

    Memory source: read_some returns min(requested, remaining).

    +
  • +
+
+
+

No concrete source type lacks a meaningful read_some. The claim that "many sources can’t meaningfully offer `read_some`" does not hold up under scrutiny.

+
+
+

The Relay Argument

+
+

If ReadSource were disjoint from ReadStream, generic relay code would need two separate implementations:

+
+
+
+
// One for ReadStream sources
+template<ReadStream Src, WriteSink Dest>
+task<> relay(Src& src, Dest& dest);
+
+// A different one for ReadSource sources
+template<ReadSource Src, WriteSink Dest>
+task<> relay(Src& src, Dest& dest);
+
+
+
+

With the refinement relationship, one function handles both:

+
+
+
+
// Works for TCP sockets, HTTP bodies, decompressors, files
+template<ReadStream Src, WriteSink Dest>
+task<> relay(Src& src, Dest& dest);
+
+
+
+

This is the same argument that justified WriteSink refining WriteStream.

+
+
+
+

The Latency Argument

+
+

With only read (complete read), a relay must wait for the entire buffer to fill before forwarding any data:

+
+
+
+
// Must fill 64KB before sending -- high latency
+auto [ec, n] = co_await src.read(mutable_buffer(buf, 65536));
+co_await dest.write_some(const_buffer(buf, n));
+
+
+
+

With read_some, data is forwarded as it becomes available:

+
+
+
+
// Returns with 1KB if that's what's available -- low latency
+auto [ec, n] = co_await src.read_some(mutable_buffer(buf, 65536));
+co_await dest.write_some(const_buffer(buf, n));
+
+
+
+

For a decompressor backed by a slow network connection, read_some lets you decompress and forward whatever is available instead of blocking until the entire buffer is filled.

+
+
+
+
+
+

Member Function Comparison

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
read_someread

Returns whatever is available (at least 1 byte)

Fills the entire buffer or errors

Low latency: forward data immediately

Higher latency: waits for full buffer

Caller loops for complete reads

Source guarantees completeness

Natural for relays and streaming

Natural for fixed-size records and structured data

+
+
+
+

Composed Algorithms

+
+
+

read(source, dynamic_buffer) — Read Until EOF

+
+
+
auto read(ReadSource auto& source,
+          DynamicBufferParam auto&& buffers,
+          std::size_t initial_amount = 2048)
+    -> io_task<std::size_t>;
+
+
+
+

Reads from the source into a dynamic buffer until EOF. The buffer grows with a 1.5x factor when filled. On success (EOF), ec is clear and n is total bytes read.

+
+
+

This is the ReadSource equivalent of the ReadStream overload. Both use the same read free function name, distinguished by concept constraints.

+
+
+
+
+
+

Use Cases

+
+
+

Reading an HTTP Body

+
+

An HTTP body with a known content length is a ReadSource. The caller reads into a buffer, and the source ensures exactly the right number of bytes are delivered.

+
+
+
+
template<ReadSource Source>
+task<std::string> read_body(Source& body, std::size_t content_length)
+{
+    std::string result(content_length, '\0');
+    auto [ec, n] = co_await body.read(
+        mutable_buffer(result.data(), result.size()));
+    if(ec)
+    {
+        result.resize(n);
+        co_return result;
+    }
+    co_return result;
+}
+
+
+
+
+

Reading into a Dynamic Buffer

+
+

When the body size is unknown (e.g., chunked encoding), read until EOF using the dynamic buffer overload.

+
+
+
+
template<ReadSource Source>
+task<std::string> read_chunked_body(Source& body)
+{
+    std::string result;
+    auto [ec, n] = co_await read(
+        body, string_dynamic_buffer(&result));
+    if(ec)
+        co_return {};
+    co_return result;
+}
+
+
+
+
+

Reading Fixed-Size Records from a Source

+
+

When a source produces structured records of known size, read guarantees each record is completely filled.

+
+
+
+
struct record
+{
+    uint32_t id;
+    char data[256];
+};
+
+template<ReadSource Source>
+task<> process_records(Source& source)
+{
+    for(;;)
+    {
+        record rec;
+        auto [ec, n] = co_await source.read(
+            mutable_buffer(&rec, sizeof(rec)));
+        if(ec == cond::eof)
+            co_return;
+        if(ec)
+            co_return;
+
+        handle_record(rec);
+    }
+}
+
+
+
+
+

Decompression with Low-Latency Relay

+
+

A decompression source wraps a ReadStream and produces decompressed data. Using read_some (inherited from ReadStream), a relay can forward decompressed data as it becomes available instead of waiting for a full buffer.

+
+
+
+
template<ReadSource Source, WriteSink Sink>
+task<> relay_decompressed(Source& inflater, Sink& dest)
+{
+    char buf[8192];
+    for(;;)
+    {
+        // read_some: decompress whatever is available
+        auto [ec, n] = co_await inflater.read_some(
+            mutable_buffer(buf));
+        if(ec == cond::eof)
+        {
+            auto [wec] = co_await dest.write_eof();
+            co_return;
+        }
+        if(ec)
+            co_return;
+
+        auto [wec, nw] = co_await dest.write(
+            const_buffer(buf, n));
+        if(wec)
+            co_return;
+    }
+}
+
+
+
+
+

Relaying from ReadSource to WriteSink

+
+

When connecting a source to a sink, read_some provides low-latency forwarding. The final chunk uses write_eof for atomic delivery plus EOF signaling.

+
+
+
+
template<ReadStream Src, WriteSink Sink>
+task<> relay(Src& src, Sink& dest)
+{
+    char buf[8192];
+    for(;;)
+    {
+        auto [ec, n] = co_await src.read_some(
+            mutable_buffer(buf));
+        if(ec == cond::eof)
+        {
+            auto [wec] = co_await dest.write_eof();
+            co_return;
+        }
+        if(ec)
+            co_return;
+
+        auto [wec, nw] = co_await dest.write(
+            const_buffer(buf, n));
+        if(wec)
+            co_return;
+    }
+}
+
+
+
+

Because ReadSource refines ReadStream, this relay accepts ReadSource types (HTTP bodies, decompressors, files) as well as raw ReadStream types (TCP sockets, TLS streams).

+
+
+
+

Type-Erased Source

+
+

The any_read_source wrapper type-erases a ReadSource behind a virtual interface. This is useful when the concrete source type is not known at compile time.

+
+
+
+
task<> handle_request(any_read_source& body)
+{
+    // Works for content-length, chunked,
+    // compressed, or any other source type
+    std::string data;
+    auto [ec, n] = co_await read(
+        body, string_dynamic_buffer(&data));
+    if(ec)
+        co_return;
+
+    process_request(data);
+}
+
+
+
+
+
+
+

Conforming Types

+
+
+

Examples of types that satisfy ReadSource:

+
+
+
    +
  • +

    HTTP content-length body: read_some returns available bytes capped by remaining length. read fills the buffer, enforcing the content length limit.

    +
  • +
  • +

    HTTP chunked body: read_some delivers available unchunked data. read decodes chunk framing and fills the buffer.

    +
  • +
  • +

    Decompression source (inflate, zstd): read_some does one decompression pass. read loops decompression until the buffer is filled.

    +
  • +
  • +

    File source: read_some is a single read() syscall. read loops until the buffer is filled or EOF.

    +
  • +
  • +

    Memory source: read_some returns available bytes. read fills the buffer from the memory region.

    +
  • +
+
+
+
+
+

Why read_some Returns No Data on EOF

+
+
+

The read_some contract (inherited from ReadStream) requires that when ec == cond::eof, n is always 0. Data and EOF are delivered in separate calls. See ReadStream: Why Errors Exclude Data for the full rationale. The key points:

+
+
+
    +
  • +

    The clean trichotomy (success/EOF/error, where data implies success) eliminates an entire class of bugs where callers accidentally drop the final bytes of a stream.

    +
  • +
  • +

    Write-side atomicity (write_eof(buffers)) serves correctness for protocol framing. Read-side piggybacking would be a minor optimization with significant API cost.

    +
  • +
  • +

    Every concrete source type naturally separates its last data delivery from its EOF indication.

    +
  • +
  • +

    POSIX read() follows the same model.

    +
  • +
+
+
+

This contract carries over to ReadSource unchanged. The read member function (complete read) does allow n > 0 on EOF, because it is a composed loop that accumulates data across multiple internal read_some calls. When the underlying stream signals EOF mid-accumulation, discarding the bytes already gathered would be wrong. The caller needs n to know how much valid data landed in the buffer.

+
+
+
+
+

Summary

+
+
+

ReadSource refines ReadStream by adding read for complete-read semantics. The refinement relationship enables:

+
+
+
    +
  • +

    Generic algorithms constrained on ReadStream work on both raw streams and sources.

    +
  • +
  • +

    read_some provides low-latency forwarding in relays.

    +
  • +
  • +

    read provides the complete-fill guarantee for structured data.

    +
  • +
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionContractUse Case

ReadSource::read_some

Returns one or more bytes. May fill less than the buffer.

Relays, low-latency forwarding, incremental processing.

ReadSource::read

Fills the entire buffer or returns an error with partial count.

HTTP bodies, decompression, file I/O, structured records.

read composed (on ReadStream)

Loops read_some until the buffer is filled.

Fixed-size headers, known-length messages over raw streams.

read composed (on ReadSource)

Loops read into a dynamic buffer until EOF.

Slurping an entire body of unknown size.

+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8e.BufferSource.html b/preview/8.design/8e.BufferSource.html new file mode 100644 index 0000000..bde7a57 --- /dev/null +++ b/preview/8.design/8e.BufferSource.html @@ -0,0 +1,1000 @@ + + + + + + + + + + + + + + BufferSource Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

BufferSource Concept Design

+
+

Overview

+
+
+

This document describes the design of the BufferSource concept, the rationale behind each member function, and the relationship between BufferSource, ReadSource, and the push_to algorithm. BufferSource models the "callee owns buffers" pattern on the read side: the source exposes its internal storage as read-only buffers and the caller consumes data directly from them, enabling zero-copy data transfer.

+
+
+

Where ReadSource requires the caller to supply mutable buffers for the source to fill, BufferSource inverts the ownership: the source provides read-only views into its own memory and the caller reads from them in place. The two concepts are independent — neither refines the other — but the type-erased wrapper any_buffer_source satisfies both, bridging the two patterns behind a single runtime interface.

+
+
+
+
+

Concept Definition

+
+
+
+
template<typename T>
+concept BufferSource =
+    requires(T& src, std::span<const_buffer> dest, std::size_t n)
+    {
+        { src.pull(dest) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(src.pull(dest)),
+            std::error_code, std::span<const_buffer>>;
+        src.consume(n);
+    };
+
+
+
+

BufferSource is a standalone concept. It does not refine ReadSource or ReadStream. The two concept families model different ownership patterns and can coexist on the same concrete type.

+
+
+
+
+

Caller vs Callee Buffer Ownership

+
+
+

The library provides two concept families for reading data:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectReadSource (caller owns)BufferSource (callee owns)

Buffer origin

Caller allocates mutable buffers; source fills them.

Source exposes its internal storage as read-only buffers; caller reads + from them.

Copy cost

One copy: source’s internal storage → caller’s buffer.

Zero copies when the caller can process data in place (e.g., scanning, + hashing, forwarding to a write_some call).

API shape

read_some(buffers), read(buffers)

pull(dest), consume(n)

Natural for

Callers that need to accumulate data into their own buffer (e.g., + parsing a fixed-size header into a struct).

Sources backed by pre-existing memory (ring buffers, memory-mapped + files, decompression output buffers, kernel receive buffers).

+
+

Both patterns are necessary. A memory-mapped file source naturally owns the mapped region; the caller reads directly from the mapped pages without copying. Conversely, an application that needs to fill a fixed-size header struct naturally provides its own mutable buffer for the source to fill.

+
+
+
+
+

Member Functions

+
+
+

pull(dest) — Expose Readable Buffers

+
+

Fills the provided span with const buffer descriptors pointing to the source’s internal storage. This operation is asynchronous because the source may need to perform I/O to produce data (e.g., reading from a socket, decompressing a block).

+
+
+

Signature

+
+
+
IoAwaitable auto pull(std::span<const_buffer> dest);
+
+
+
+

Returns (error_code, std::span<const_buffer>).

+
+
+
+

Semantics

+
+
    +
  • +

    Data available: !ec and bufs.size() > 0. The returned span contains buffer descriptors pointing to readable data in the source’s internal storage.

    +
  • +
  • +

    Source exhausted: ec == cond::eof and bufs.empty(). No more data is available; the transfer is complete.

    +
  • +
  • +

    Error: ec is true and ec != cond::eof. An error occurred.

    +
  • +
+
+
+

Calling pull multiple times without an intervening consume returns the same unconsumed data. This idempotency lets the caller inspect the data, decide how much to process, and then advance the position with consume.

+
+
+
+

Why Asynchronous

+
+

Unlike BufferSink::prepare, which is synchronous, pull is asynchronous. The asymmetry exists because the two operations have fundamentally different costs:

+
+
+
    +
  • +

    prepare returns pointers to empty memory the sink already owns. No data movement is involved; it is pure bookkeeping.

    +
  • +
  • +

    pull may need to produce data before it can return buffer descriptors. A file source reads from disk. A decompression source feeds compressed input to the decompressor. A network source waits for data to arrive on a socket. These operations require I/O.

    +
  • +
+
+
+

Making pull synchronous would force the source to pre-buffer all data before the caller can begin consuming it, defeating the streaming model.

+
+
+
+

Why a Span Parameter

+
+

The caller provides the output span rather than the source returning a fixed-size container. This lets the caller control the stack allocation and avoids heap allocation for the buffer descriptor array:

+
+
+
+
const_buffer arr[16];
+auto [ec, bufs] = co_await source.pull(arr);
+
+
+
+

The source fills as many descriptors as it can (up to dest.size()) and returns the populated subspan.

+
+
+
+
+

consume(n) — Advance the Read Position

+
+

Advances the source’s internal read position by n bytes. The next call to pull returns data starting after the consumed bytes. This operation is synchronous.

+
+
+

Signature

+
+
+
void consume(std::size_t n) noexcept;
+
+
+
+
+

Semantics

+
+
    +
  • +

    Advances the read position by n bytes.

    +
  • +
  • +

    n must not exceed the total size of the buffers returned by the most recent pull.

    +
  • +
  • +

    After consume, the buffers returned by the prior pull are invalidated. The caller must call pull again to obtain new buffer descriptors.

    +
  • +
+
+
+
+

Why Synchronous

+
+

consume is synchronous because it is pure bookkeeping: advancing an offset or releasing a reference. No I/O is involved. The asynchronous work (producing data, performing I/O) happens in pull.

+
+
+
+

Why Separate from pull

+
+

Separating consume from pull gives the caller explicit control over how much data to process before advancing:

+
+
+
+
const_buffer arr[16];
+auto [ec, bufs] = co_await source.pull(arr);
+if(!ec)
+{
+    // Process some of the data
+    auto n = process(bufs);
+    source.consume(n);
+    // Remaining data returned by next pull
+}
+
+
+
+

This is essential for partial processing. A parser may examine the pulled data, find that it contains an incomplete message, and consume only the complete portion. The next pull returns the remainder prepended to any newly available data.

+
+
+

If pull automatically consumed all returned data, the caller would need to buffer unconsumed bytes itself, defeating the zero-copy benefit.

+
+
+
+
+
+
+

The Pull/Consume Protocol

+
+
+

The pull and consume functions form a two-phase read protocol:

+
+
+
    +
  1. +

    Pull: the source provides data (async, may involve I/O).

    +
  2. +
  3. +

    Inspect: the caller examines the returned buffers.

    +
  4. +
  5. +

    Consume: the caller indicates how many bytes were used (sync).

    +
  6. +
  7. +

    Repeat: the next pull returns data starting after the consumed bytes.

    +
  8. +
+
+
+

This protocol enables several patterns that a single-call interface cannot:

+
+
+
    +
  • +

    Partial consumption: consume less than what was pulled. The remainder is returned by the next pull.

    +
  • +
  • +

    Peek: call pull to inspect data without consuming it. Call pull again (without consume) to get the same data.

    +
  • +
  • +

    Scatter writes: pull once, write the returned buffers to multiple destinations (e.g., write_some to a socket), and consume only the bytes that were successfully written.

    +
  • +
+
+
+
+
+

Relationship to push_to

+
+
+

push_to is a composed algorithm that transfers data from a BufferSource to a WriteSink (or WriteStream). It is the callee-owns-buffers counterpart to pull_from, which transfers from a ReadSource (or ReadStream) to a BufferSink.

+
+
+
+
template<BufferSource Src, WriteSink Sink>
+io_task<std::size_t>
+push_to(Src& source, Sink& sink);
+
+template<BufferSource Src, WriteStream Stream>
+io_task<std::size_t>
+push_to(Src& source, Stream& stream);
+
+
+
+

The algorithm loops:

+
+
+
    +
  1. +

    Call source.pull(arr) to get readable buffers.

    +
  2. +
  3. +

    Write the data to the sink via sink.write(bufs) or stream.write_some(bufs).

    +
  4. +
  5. +

    Call source.consume(n) to advance past the written bytes.

    +
  6. +
  7. +

    When pull signals EOF, call sink.write_eof() to finalize the sink (WriteSink overload only).

    +
  8. +
+
+
+

The two push_to overloads differ in how they write to the destination:

+
+ ++++ + + + + + + + + + + + + + + + + +
OverloadBehavior

push_to(BufferSource, WriteSink)

Uses sink.write(bufs) for complete writes. Each iteration delivers + all pulled data. On EOF, calls sink.write_eof() to finalize.

push_to(BufferSource, WriteStream)

Uses stream.write_some(bufs) for partial writes. Consumes only the + bytes that were actually written, providing backpressure. Does not + signal EOF (WriteStream has no EOF mechanism).

+
+

push_to is the right tool when the data source satisfies BufferSource and the destination satisfies WriteSink or WriteStream. The source’s internal buffers are passed directly to the write call, avoiding any intermediate caller-owned buffer.

+
+
+
+
+

Relationship to ReadSource

+
+
+

BufferSource and ReadSource are independent concepts serving different ownership models. A concrete type may satisfy one, the other, or both.

+
+
+

The type-erased wrapper any_buffer_source satisfies both concepts. When the wrapped type satisfies only BufferSource, the ReadSource operations (read_some, read) are synthesized from pull and consume with a buffer_copy step: the wrapper pulls data from the underlying source, copies it into the caller’s mutable buffers, and consumes the copied bytes.

+
+
+

When the wrapped type satisfies both BufferSource and ReadSource, the native read_some and read implementations are forwarded directly across the type-erased boundary, avoiding the extra copy. This dispatch is determined at compile time when the vtable is constructed; at runtime the wrapper checks a single nullable function pointer to select the forwarding path.

+
+
+

This dual-concept bridge lets algorithms constrained on ReadSource work with any BufferSource through any_buffer_source, and lets algorithms constrained on BufferSource work natively with the callee-owns-buffers pattern.

+
+
+

Transfer Algorithm Matrix

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SourceSinkAlgorithm

BufferSource

WriteSink

push_to — pulls from source, writes to sink, signals EOF

BufferSource

WriteStream

push_to — pulls from source, writes partial to stream

ReadSource

BufferSink

pull_from — prepares sink buffers, reads into them

ReadStream

BufferSink

pull_from — prepares sink buffers, reads partial into them

+
+
+
+
+

Use Cases

+
+
+

Zero-Copy Transfer to a Socket

+
+

When the source’s internal storage already contains the data to send, push_to passes the source’s buffers directly to the socket’s write_some, avoiding any intermediate copy.

+
+
+
+
template<BufferSource Source, WriteStream Stream>
+task<> send_all(Source& source, Stream& socket)
+{
+    auto [ec, total] = co_await push_to(source, socket);
+    if(ec)
+        co_return;
+    // total bytes sent directly from source's internal buffers
+}
+
+
+
+
+

Memory-Mapped File Source

+
+

A memory-mapped file is a natural BufferSource. The pull operation returns buffer descriptors pointing directly into the mapped region. No data is copied until the consumer explicitly copies it.

+
+
+
+
template<BufferSource Source, WriteSink Sink>
+task<> serve_static_file(Source& mmap_source, Sink& response)
+{
+    auto [ec, total] = co_await push_to(mmap_source, response);
+    if(ec)
+        co_return;
+    // File served via zero-copy from mapped pages
+}
+
+
+
+
+

Partial Consumption with a Parser

+
+

A protocol parser pulls data, parses as much as it can, and consumes only the parsed portion. The next pull returns the unparsed remainder plus any newly arrived data.

+
+
+
+
template<BufferSource Source>
+task<message> parse_message(Source& source)
+{
+    const_buffer arr[16];
+    message msg;
+
+    for(;;)
+    {
+        auto [ec, bufs] = co_await source.pull(arr);
+        if(ec)
+            co_return msg;
+
+        auto [parsed, complete] = msg.parse(bufs);
+        source.consume(parsed);
+
+        if(complete)
+            co_return msg;
+    }
+}
+
+
+
+

The parser consumes only the bytes it understood. If a message spans two pull calls, the unconsumed tail from the first call is returned at the start of the second.

+
+
+
+

HTTP Request Body Source

+
+

An HTTP request body can be exposed through a BufferSource interface. The concrete implementation handles transfer encoding (content-length, chunked, compressed) behind the abstraction.

+
+
+
+
task<> handle_request(
+    any_buffer_source& body,
+    WriteSink auto& response)
+{
+    auto [ec, total] = co_await push_to(body, response);
+    if(ec)
+        co_return;
+    // Request body forwarded to response sink
+}
+
+
+
+

The caller does not know whether the body uses content-length, chunked encoding, or compression. The BufferSource interface handles the difference.

+
+
+
+

Bridging to ReadSource via any_buffer_source

+
+

When a function is constrained on ReadSource but the concrete type satisfies only BufferSource, any_buffer_source bridges the gap.

+
+
+
+
template<ReadSource Source>
+task<std::string> read_all(Source& source);
+
+// Concrete type satisfies BufferSource only
+my_ring_buffer ring;
+any_buffer_source abs(ring);
+
+// Works: any_buffer_source satisfies ReadSource
+auto data = co_await read_all(abs);
+
+
+
+

The read_some and read methods pull data internally, copy it into the caller’s mutable buffers, and consume the copied bytes. This incurs one buffer copy compared to using pull and consume directly.

+
+
+
+
+
+

Alternatives Considered

+
+
+

Single pull That Auto-Consumes

+
+

An earlier design had pull automatically consume all returned data, eliminating the separate consume call. This was rejected because:

+
+
+
    +
  • +

    Partial consumption becomes impossible. A parser that finds an incomplete message at the end of a pull would need to buffer the remainder itself, negating the zero-copy benefit.

    +
  • +
  • +

    Peek semantics (inspecting data without consuming it) require the source to maintain a separate undo mechanism.

    +
  • +
  • +

    The WriteStream::write_some pattern naturally consumes only n bytes, so the remaining pulled data must survive for the next write_some call. Without consume, the source would need to track how much of its own returned data was actually used.

    +
  • +
+
+
+
+

pull Returning an Owned Container

+
+

A design where pull returned a std::vector<const_buffer> or similar owned container was considered. This was rejected because:

+
+
+
    +
  • +

    Heap allocation on every pull is unacceptable for high-throughput I/O paths.

    +
  • +
  • +

    The span-based interface lets the caller control storage: a stack-allocated array for the common case, or a heap-allocated array for unusual situations.

    +
  • +
  • +

    Returning a subspan of the caller’s span is zero-overhead and composes naturally with existing buffer algorithm interfaces.

    +
  • +
+
+
+
+

Synchronous pull

+
+

Making pull synchronous (like BufferSink::prepare) was considered. This was rejected because:

+
+
+
    +
  • +

    A source may need to perform I/O to produce data. A file source reads from disk. A decompression source feeds compressed input to the decompressor. A network source waits for data to arrive.

    +
  • +
  • +

    Forcing synchronous pull would require the source to pre-buffer all data before the caller starts consuming, breaking the streaming model and inflating memory usage.

    +
  • +
  • +

    The asymmetry with prepare is intentional: prepare returns pointers to empty memory (no I/O needed), while pull returns pointers to data that may need to be produced first.

    +
  • +
+
+
+
+

BufferSource Refining ReadSource

+
+

A design where BufferSource refined ReadSource (requiring all types to implement read_some and read) was considered. This was rejected because:

+
+
+
    +
  • +

    Many natural BufferSource types (memory-mapped files, ring buffers, DMA receive descriptors) have no meaningful read_some primitive. Their data path is pull-then-consume, not read-into-caller-buffer.

    +
  • +
  • +

    Requiring read_some and read on every BufferSource would force implementations to synthesize these operations even when they are never called.

    +
  • +
  • +

    The any_buffer_source wrapper provides the bridge when needed, without burdening every concrete type.

    +
  • +
+
+
+
+

Combined Pull-and-Consume

+
+

A design with a single read(dest) → (error_code, span) that both pulled and advanced the position was considered. This is equivalent to the auto-consume alternative above and was rejected for the same reasons: it prevents partial consumption and peek semantics.

+
+
+
+
+
+

Summary

+
+ +++++ + + + + + + + + + + + + + + + + + + + +
FunctionContractUse Case

pull(dest)

Async. Fills span with readable buffer descriptors from the source’s + internal storage. Returns EOF when exhausted.

Every read iteration: obtain data to process or forward.

consume(n)

Sync. Advances the read position by n bytes. Invalidates prior + buffers.

After processing or forwarding data: indicate how much was used.

+
+

BufferSource is the callee-owns-buffers counterpart to ReadSource. The push_to algorithm transfers data from a BufferSource to a WriteSink or WriteStream, and any_buffer_source bridges the two patterns by satisfying both BufferSource and ReadSource behind a single type-erased interface.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8f.WriteStream.html b/preview/8.design/8f.WriteStream.html new file mode 100644 index 0000000..7820848 --- /dev/null +++ b/preview/8.design/8f.WriteStream.html @@ -0,0 +1,808 @@ + + + + + + + + + + + + + + WriteStream Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

WriteStream Concept Design

+
+

Overview

+
+
+

This document describes the design of the WriteStream concept: the fundamental partial-write primitive in the concept hierarchy. It explains why write_some is the correct building block, how algorithms expressed directly in terms of write_some can outperform composed complete-write algorithms like write_now, and when each approach is appropriate.

+
+
+
+
+

Definition

+
+
+
+
template<typename T>
+concept WriteStream =
+    requires(T& stream, const_buffer_archetype buffers)
+    {
+        { stream.write_some(buffers) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(stream.write_some(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+

A WriteStream provides a single operation:

+
+
+

write_some(buffers) — Partial Write

+
+

Writes one or more bytes from the buffer sequence. Returns (error_code, std::size_t) where n is the number of bytes written.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n >= 1 and n <= buffer_size(buffers).

    +
  • +
  • +

    On error: ec, n == 0.

    +
  • +
  • +

    If buffer_empty(buffers): completes immediately, !ec, n == 0.

    +
  • +
+
+
+

The caller must not assume that all bytes are consumed. write_some may write fewer bytes than offered. This is the defining property of a partial-write primitive.

+
+
+
+

Buffer Lifetime

+
+

The caller must ensure that the memory referenced by buffers remains valid until the co_await expression returns.

+
+
+
+

Conforming Signatures

+
+
+
template<ConstBufferSequence Buffers>
+IoAwaitable auto write_some(Buffers buffers);
+
+
+
+

Buffer sequences should be accepted by value when the member function is a coroutine, to ensure the sequence lives in the coroutine frame across suspension points.

+
+
+
+
+
+
+

Concept Hierarchy

+
+
+

WriteStream is the base of the write-side hierarchy:

+
+
+
+
WriteStream   { write_some }
+    |
+    v
+WriteSink     { write_some, write, write_eof(buffers), write_eof() }
+
+
+
+

Every WriteSink is a WriteStream. Algorithms constrained on WriteStream accept both raw streams and sinks. The WriteSink concept adds complete-write and EOF signaling on top of the partial-write primitive. See the WriteSink design document for details.

+
+
+
+
+

Composed Algorithms

+
+
+

Two composed algorithms build complete-write behavior on top of write_some:

+
+
+

write (free function)

+
+
+
auto write(WriteStream auto& stream,
+           ConstBufferSequence auto const& buffers)
+    -> io_task<std::size_t>;
+
+
+
+

Loops write_some until the entire buffer sequence is consumed. Always suspends (returns task). No frame caching.

+
+
+
+

write_now (class template)

+
+
+
template<WriteStream Stream>
+class write_now
+{
+public:
+    explicit write_now(Stream& s) noexcept;
+
+    IoAwaitable auto operator()(ConstBufferSequence auto buffers);
+};
+
+
+
+

Loops write_some until the entire buffer sequence is consumed, with two advantages over the free function:

+
+
+
    +
  1. +

    Eager completion: if every write_some returns synchronously (its await_ready returns true), the entire operation completes in await_ready with zero coroutine suspensions.

    +
  2. +
  3. +

    Frame caching: the internal coroutine frame is allocated once and reused across calls.

    +
  4. +
+
+
+
+
+
+

Buffer Top-Up: Why write_some Can Outperform write_now

+
+
+

The critical design insight behind write_some as a primitive is that the caller retains control after each partial write. This enables a pattern called buffer top-up: after a partial write consumes some data, the caller refills the buffer before the next write, keeping the buffer as full as possible. This maximizes the payload of each system call.

+
+
+

A composed algorithm like write_now cannot do this. It receives a fixed buffer sequence and drains it to completion. When the kernel accepts only part of the data, write_now must send the remainder in a second call — even though the remainder may be small. The caller has no opportunity to read more data from the source between iterations.

+
+
+

Diagram: Relaying 100KB from a ReadSource through a TCP Socket

+
+

Consider relaying 100KB from a ReadSource to a TCP socket. The kernel’s send buffer accepts at most 40KB per call. Compare two approaches:

+
+
+

Approach A: write_some with Top-Up (3 syscalls)

+
+
+
          buffer contents          syscall        kernel accepts
+Step 1:   [======== 64KB ========] write_some --> 40KB, read 40KB from source
+Step 2:   [======== 64KB ========] write_some --> 40KB, read 20KB (source done)
+Step 3:   [===== 44KB =====]       write_some --> 44KB
+          done. 100KB in 3 syscalls, every call near-full.
+
+
+
+
+

Approach B: write_now Without Top-Up (4 syscalls)

+
+
+
          buffer contents          syscall        kernel accepts
+Step 1:   [======== 64KB ========] write_some --> 40KB  (write_now, read 64KB)
+Step 2:   [=== 24KB ===]           write_some --> 24KB  (write_now, small payload)
+Step 3:   [====== 36KB ======]     write_some --> 20KB  (write_now, read 36KB)
+Step 4:   [== 16KB ==]             write_some --> 16KB  (write_now, small payload)
+          done. 100KB in 4 syscalls, two calls undersized.
+
+
+
+

Every time write_now partially drains a buffer, the remainder is a small payload that wastes a syscall. With top-up, the caller refills the ring buffer between calls, keeping each syscall near capacity.

+
+
+
+
+

Code: write_some with Buffer Top-Up

+
+

This example reads from a ReadSource and writes to a WriteStream using a circular_dynamic_buffer. After each partial write frees space in the ring buffer, the caller reads more data from the source to refill it before calling write_some again.

+
+
+
+
template<ReadSource Source, WriteStream Stream>
+task<> relay_with_topup(Source& src, Stream& dest)
+{
+    char storage[65536];
+    circular_dynamic_buffer cb(storage, sizeof(storage));
+
+    for(;;)
+    {
+        // Fill: read from source into free space
+        auto mb = cb.prepare(cb.capacity());
+        auto [rec, nr] = co_await src.read(mb);
+        cb.commit(nr);
+        if(rec && rec != cond::eof && nr == 0)
+            co_return;
+
+        // Drain: write_some from the ring buffer
+        while(cb.size() > 0)
+        {
+            auto [wec, nw] = co_await dest.write_some(
+                cb.data());
+            if(wec)
+                co_return;
+
+            // consume only what was written
+            cb.consume(nw);
+
+            // Top-up: refill freed space before next
+            // write_some, so the next call presents
+            // the largest possible payload
+            if(cb.capacity() > 0 && rec != cond::eof)
+            {
+                auto mb2 = cb.prepare(cb.capacity());
+                auto [rec2, nr2] = co_await src.read(mb2);
+                cb.commit(nr2);
+                rec = rec2;
+            }
+            // write_some now sees a full (or nearly full)
+            // ring buffer, maximizing the syscall payload
+        }
+
+        if(rec == cond::eof)
+            co_return;
+    }
+}
+
+
+
+

After write_some accepts 40KB of a 64KB buffer, consume(40KB) frees 40KB. The caller immediately reads more data from the source into that freed space. The next write_some again presents a full 64KB payload.

+
+
+
+

Code: write_now Without Top-Up

+
+

This example reads from a ReadSource and writes to a WriteStream using write_now. Each chunk is drained to completion before the caller can read more from the source.

+
+
+
+
template<ReadSource Source, WriteStream Stream>
+task<> relay_with_write_now(Source& src, Stream& dest)
+{
+    char buf[65536];
+    write_now wn(dest);
+
+    for(;;)
+    {
+        // Read a chunk from the source
+        auto [rec, nr] = co_await src.read(
+            mutable_buffer(buf, sizeof(buf)));
+        if(rec == cond::eof && nr == 0)
+            co_return;
+
+        // write_now drains the chunk to completion.
+        // If the kernel accepts 40KB of 64KB, write_now
+        // internally calls write_some(24KB) for the
+        // remainder -- a small write that wastes a
+        // syscall. The caller cannot top up between
+        // write_now's internal iterations.
+        auto [wec, nw] = co_await wn(
+            const_buffer(buf, nr));
+        if(wec)
+            co_return;
+
+        if(rec == cond::eof)
+            co_return;
+    }
+}
+
+
+
+

After the kernel accepts 40KB of a 64KB chunk, write_now must send the remaining 24KB in a second write_some. The caller cannot intervene to refill the buffer because write_now owns the loop. That 24KB write wastes an opportunity to send a full 64KB payload.

+
+
+
+
+
+

When to Use Each Approach

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ApproachBest ForTrade-off

write_some directly

High-throughput relays, producer-consumer loops where the + caller has more data available and can top up after partial writes.

Caller manages the loop and buffer refill.

write_now

Writing discrete complete payloads (a single HTTP header, a + serialized message) where there is no additional data to top up with, + or where the write is expected to complete in one call.

Cannot top up between iterations. Small remainders + waste syscall payloads.

WriteSink::write

Sink-oriented code where the concrete type implements complete-write + natively (buffered writer, file, compressor) and the caller does not + manage the loop.

Requires WriteSink, not just WriteStream.

+
+

Rule of Thumb

+
+
    +
  • +

    If the caller reads from a source and relays to a raw byte stream (TCP socket), use write_some with a circular_dynamic_buffer for buffer top-up.

    +
  • +
  • +

    If the caller has a discrete, bounded payload and wants zero-fuss complete-write semantics, use write_now.

    +
  • +
  • +

    If the destination is a WriteSink, use write directly.

    +
  • +
+
+
+
+
+
+

Conforming Types

+
+
+

Examples of types that satisfy WriteStream:

+
+
+
    +
  • +

    TCP sockets: write_some maps to a single send() or WSASend() call. Partial writes are normal under load.

    +
  • +
  • +

    TLS streams: write_some encrypts and sends one TLS record.

    +
  • +
  • +

    Buffered write streams: write_some appends to an internal buffer and returns immediately when space is available, or drains to the underlying stream when full.

    +
  • +
  • +

    QUIC streams: write_some sends one or more QUIC frames.

    +
  • +
  • +

    Test mock streams: write_some records data and returns configurable results for testing.

    +
  • +
+
+
+

All of these types also naturally extend to WriteSink by adding write, write_eof(buffers), and write_eof().

+
+
+
+
+

Relationship to ReadStream

+
+
+

The read-side counterpart is ReadStream, which requires read_some. The same partial-transfer / composed-algorithm decomposition applies:

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
Write SideRead Side

WriteStream::write_some

ReadStream::read_some

write_now (composed)

read free function (composed)

WriteSink::write

ReadSource::read

+
+

The asymmetry is that the read side does not have a read_now with eager completion, because reads depend on data arriving from the network — the synchronous fast path is less reliably useful than for writes into a buffered stream.

+
+
+
+
+

Summary

+
+
+

WriteStream provides write_some as the single partial-write primitive. This is deliberately minimal:

+
+
+
    +
  • +

    Algorithms that need complete-write semantics use write_now (for WriteStream) or write (for WriteSink).

    +
  • +
  • +

    Algorithms that need maximum throughput use write_some directly with buffer top-up, achieving fewer syscalls than composed algorithms by keeping the buffer full between iterations.

    +
  • +
  • +

    The concept is the base of the hierarchy. WriteSink refines it by adding write, write_eof(buffers), and write_eof().

    +
  • +
+
+
+

The choice between write_some, write_now, and WriteSink::write is a throughput-versus-convenience trade-off. write_some gives the caller maximum control. write_now gives the caller maximum simplicity. WriteSink::write gives the concrete type maximum implementation freedom.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8g.WriteSink.html b/preview/8.design/8g.WriteSink.html new file mode 100644 index 0000000..209801a --- /dev/null +++ b/preview/8.design/8g.WriteSink.html @@ -0,0 +1,930 @@ + + + + + + + + + + + + + + WriteSink Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

WriteSink Concept Design

+
+

Overview

+
+
+

This document describes the design of the WriteSink concept, the rationale behind each member function, and the relationship between WriteSink, WriteStream, and the write_now algorithm. The design was arrived at through deliberation over several alternative approaches, each of which is discussed here with its trade-offs.

+
+
+
+
+

Concept Hierarchy

+
+
+

The write-side concept hierarchy consists of two concepts:

+
+
+
+
// Partial write primitive
+template<typename T>
+concept WriteStream =
+    requires(T& stream, const_buffer_archetype buffers)
+    {
+        { stream.write_some(buffers) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(stream.write_some(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+// Complete write with EOF signaling
+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>;
+    };
+
+
+
+

WriteSink refines WriteStream. Every WriteSink is a WriteStream. Algorithms constrained on WriteStream accept both raw streams and sinks.

+
+
+
+
+

Member Functions

+
+
+

write_some(buffers) — Partial Write

+
+

Writes one or more bytes from the buffer sequence. May consume less than the full sequence. Returns (error_code, std::size_t) where n is the number of bytes written.

+
+
+

This is the low-level primitive inherited from WriteStream. It is appropriate when the caller manages its own consumption loop or when forwarding data incrementally without needing a complete-write guarantee.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n >= 1.

    +
  • +
  • +

    On error: ec, n == 0.

    +
  • +
  • +

    If buffer_empty(buffers): completes immediately, !ec, n == 0.

    +
  • +
+
+
+
+

When to Use

+
+
    +
  • +

    Relay interiors: forwarding chunks of data as they arrive without waiting for the entire payload to be consumed.

    +
  • +
  • +

    Backpressure-aware pipelines: writing what the destination can accept and returning control to the caller.

    +
  • +
  • +

    Implementing write or write_now on top of the primitive.

    +
  • +
+
+
+
+
+

write(buffers) — Complete Write

+
+

Writes the entire buffer sequence. All bytes are consumed before the operation completes. Returns (error_code, std::size_t) where n is the number of bytes written.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n == buffer_size(buffers).

    +
  • +
  • +

    On error: ec, n is the number of bytes written before the error occurred.

    +
  • +
  • +

    If buffer_empty(buffers): completes immediately, !ec, n == 0.

    +
  • +
+
+
+
+

When to Use

+
+
    +
  • +

    Writing complete protocol messages or frames.

    +
  • +
  • +

    Serializing structured data where each fragment must be fully delivered before producing the next.

    +
  • +
  • +

    Any context where partial delivery is not meaningful.

    +
  • +
+
+
+
+

Why write Belongs in the Concept

+
+

For many concrete types, write is the natural primitive, not a loop over write_some:

+
+
+
    +
  • +

    File sinks: the OS write call is the primitive. write_some would simply delegate to write.

    +
  • +
  • +

    Buffered writers: write is a memcpy into the circular buffer (or drain-then-copy). It is not a loop over write_some.

    +
  • +
  • +

    Compression sinks (deflate, zstd): write feeds data to the compressor and flushes the output. The internal operation is a single compression call, not iterated partial writes.

    +
  • +
+
+
+

Requiring write in the concept lets each type implement the operation in the way that is natural and efficient for that type.

+
+
+
+
+

write_eof(buffers) — Atomic Final Write

+
+

Writes the entire buffer sequence and then signals end-of-stream, as a single atomic operation. Returns (error_code, std::size_t) where n is the number of bytes written.

+
+
+

After a successful call, no further writes or EOF signals are permitted.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec, n == buffer_size(buffers). The sink is finalized.

    +
  • +
  • +

    On error: ec, n is bytes written before the error. The sink state is unspecified.

    +
  • +
+
+
+
+

Why Atomicity Matters

+
+

Combining the final write with the EOF signal in a single operation enables optimizations that two separate calls cannot:

+
+
+
    +
  • +

    HTTP chunked encoding: write_eof(data) can emit the data chunk followed by the terminal 0\r\n\r\n in a single system call. Calling write(data) then write_eof() separately forces two calls and may result in two TCP segments.

    +
  • +
  • +

    Compression (deflate): write_eof(data) can pass Z_FINISH to the final deflate() call, producing the compressed data and the stream trailer together. Separate write + write_eof would require an extra flush.

    +
  • +
  • +

    TLS close-notify: write_eof(data) can coalesce the final application data with the TLS close-notify alert.

    +
  • +
+
+
+

This optimization cannot be achieved by splitting the operation into write(data) followed by write_eof().

+
+
+
+
+

write_eof() — Bare EOF Signal

+
+

Signals end-of-stream without writing any data. Returns (error_code).

+
+
+

After a successful call, no further writes or EOF signals are permitted.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec. The sink is finalized.

    +
  • +
  • +

    On error: ec.

    +
  • +
+
+
+
+

When to Use

+
+

When the final data has already been written via write or write_some and only the EOF signal remains. This is less common than write_eof(buffers) but necessary when the data and EOF are produced at different times.

+
+
+
+
+
+
+

Relationship to write_now

+
+
+

write_now is a composed algorithm that operates on any WriteStream. It loops write_some until the entire buffer sequence is consumed. It has two properties that a plain write_some loop does not:

+
+
+
    +
  1. +

    Eager completion: if every write_some call completes synchronously (returns true from await_ready), the entire write_now operation completes in await_ready with zero coroutine suspensions.

    +
  2. +
  3. +

    Frame caching: the internal coroutine frame is cached and reused across calls, eliminating repeated allocation.

    +
  4. +
+
+
+

write_now is the right tool for code constrained on WriteStream alone (for example, writing to a raw TCP socket). Code constrained on WriteSink should use write directly, because the concrete type’s write may be more efficient than looping write_some, and because write_now cannot replicate the atomic write_eof(buffers) operation.

+
+
+
+
+

Use Cases

+
+
+

Serializing Structured Data

+
+

When producing output fragment by fragment (e.g., JSON serialization), each fragment must be fully consumed before the next is produced. The final fragment signals EOF.

+
+
+
+
template<WriteSink Sink>
+task<> serialize_json(Sink& sink, json::value const& jv)
+{
+    auto [ec1, n1] = co_await sink.write(make_buffer("{"));
+    if(ec1)
+        co_return;
+
+    auto body = serialize_fields(jv);
+    auto [ec2, n2] = co_await sink.write(make_buffer(body));
+    if(ec2)
+        co_return;
+
+    auto [ec3, n3] = co_await sink.write_eof(make_buffer("}"));
+    if(ec3)
+        co_return;
+}
+
+
+
+

Here write guarantees each fragment is fully delivered, and write_eof atomically writes the closing brace and finalizes the sink.

+
+
+
+

Relaying a Streaming Body

+
+

When forwarding data from a source to a sink, the interior chunks use write_some for incremental progress. The final chunk uses write_eof for atomic delivery plus EOF.

+
+
+
+
template<ReadStream Source, WriteSink Sink>
+task<> relay(Source& src, Sink& dest)
+{
+    char buf[8192];
+    for(;;)
+    {
+        auto [ec, n] = co_await src.read_some(
+            mutable_buffer(buf));
+        if(ec == cond::eof)
+        {
+            // Signal EOF to the destination
+            auto [ec2] = co_await dest.write_eof();
+            co_return;
+        }
+        if(ec)
+            co_return;
+
+        // Interior: partial write is acceptable
+        std::size_t written = 0;
+        while(written < n)
+        {
+            auto [ec2, n2] = co_await dest.write_some(
+                const_buffer(buf + written, n - written));
+            if(ec2)
+                co_return;
+            written += n2;
+        }
+    }
+}
+
+
+
+

The interior loop uses write_some because the relay does not need complete-write guarantees for intermediate data. When read_some returns EOF, n is 0 (per the ReadStream contract), so the relay signals EOF via write_eof() with no data.

+
+
+
+

Writing Complete Messages

+
+

When sending discrete messages where each must be fully delivered, write is the natural choice.

+
+
+
+
template<WriteSink Sink>
+task<> send_messages(Sink& sink, std::span<std::string> messages)
+{
+    for(auto const& msg : messages)
+    {
+        auto [ec, n] = co_await sink.write(make_buffer(msg));
+        if(ec)
+            co_return;
+    }
+    auto [ec] = co_await sink.write_eof();
+    if(ec)
+        co_return;
+}
+
+
+
+
+

HTTP Response Body

+
+

An HTTP response handler writes the body through a type-erased sink. The concrete implementation handles transfer encoding (content-length, chunked, compressed) behind the WriteSink interface.

+
+
+
+
task<> send_response(any_write_sink& body, response const& resp)
+{
+    // Write headers portion of body
+    auto headers = format_headers(resp);
+    auto [ec1, n1] = co_await body.write(make_buffer(headers));
+    if(ec1)
+        co_return;
+
+    // Write body with EOF
+    auto [ec2, n2] = co_await body.write_eof(
+        make_buffer(resp.body));
+    if(ec2)
+        co_return;
+}
+
+
+
+

The caller does not know whether the body is content-length, chunked, or compressed. The WriteSink interface handles the difference.

+
+
+
+

Compression Pipeline

+
+

A deflate sink wraps an underlying WriteStream and compresses data on the fly. write_eof sets Z_FINISH on the final deflate call.

+
+
+
+
template<WriteSink Sink>
+task<> compress_and_send(Sink& sink, std::string_view data)
+{
+    // Write compressed data
+    auto [ec, n] = co_await sink.write_eof(make_buffer(data));
+    if(ec)
+        co_return;
+    // sink.write_eof triggered Z_FINISH internally,
+    // flushing the final compressed block and trailer
+}
+
+
+
+
+

Buffered Writer

+
+

A buffered writer interposes a buffer between the caller and the underlying stream. write_some appends to the buffer without draining. write ensures all data is buffered (draining if necessary). write_eof flushes the buffer and signals EOF to the underlying stream.

+
+
+
+
template<WriteSink Sink>
+task<> buffered_output(Sink& sink)
+{
+    // Small writes accumulate in the buffer
+    auto [ec1, n1] = co_await sink.write(make_buffer("key: "));
+    if(ec1)
+        co_return;
+
+    auto [ec2, n2] = co_await sink.write(make_buffer("value\r\n"));
+    if(ec2)
+        co_return;
+
+    // Final write flushes buffer + signals EOF
+    auto [ec3, n3] = co_await sink.write_eof(
+        make_buffer("end\r\n"));
+    if(ec3)
+        co_return;
+}
+
+
+
+
+

Raw Stream with write_now

+
+

When only a WriteStream is available (no EOF signaling needed), the write_now algorithm provides complete-write behavior with eager completion and frame caching.

+
+
+
+
template<WriteStream Stream>
+task<> send_data(Stream& stream)
+{
+    write_now wn(stream);
+
+    auto [ec1, n1] = co_await wn(make_buffer("hello"));
+    if(ec1)
+        co_return;
+
+    // Frame is cached; no allocation on second call
+    auto [ec2, n2] = co_await wn(make_buffer("world"));
+    if(ec2)
+        co_return;
+}
+
+
+
+

Because WriteSink refines WriteStream, write_now also works on sinks. This can be useful when a function is generic over WriteStream and does not need EOF signaling.

+
+
+
+
+
+

Alternatives Considered

+
+
+

WriteSink with Only write and write_eof

+
+

The initial design had WriteSink require only write(buffers), write(buffers, bool eof), and write_eof(), with no write_some. This made WriteSink disjoint from WriteStream: a function constrained on WriteStream (using write_some) could not accept a WriteSink, and vice versa.

+
+
+

This was rejected because it prevents generic algorithms from working across both streams and sinks. The refinement relationship (WriteSink refines WriteStream) is strictly more useful.

+
+
+
+

WriteSink with Only write_some and write_eof

+
+

A minimal design was considered where WriteSink required only write_some and write_eof, with callers using write_now for complete-write behavior. This approach has three problems:

+
+
+
    +
  1. +

    No atomic final write: write_now over write_some followed by write_eof() is two operations. This prevents concrete types from coalescing the final data with the EOF signal (chunked encoding, compression trailers, TLS close-notify).

    +
  2. +
  3. +

    write is the natural primitive for many types: files, buffered writers, and compression sinks implement write directly, not as a loop over write_some. Forcing these types to express complete-write semantics through a function called write_some is semantically misleading.

    +
  4. +
  5. +

    Implementation burden on callers: every caller that needs complete-write behavior must construct a write_now object and manage it, rather than calling sink.write(buffers) directly.

    +
  6. +
+
+
+
+

write(buffers, bool eof) Instead of write_eof(buffers)

+
+

An earlier version used write(buffers, bool eof) to combine data writing with optional EOF signaling. This was replaced by write_eof(buffers) because:

+
+
+
    +
  • +

    Boolean parameters are opaque at the call site. write(data, true) does not convey intent as clearly as write_eof(data).

    +
  • +
  • +

    write_eof is self-documenting: the name states that EOF is signaled.

    +
  • +
  • +

    No risk of accidentally passing the wrong boolean value.

    +
  • +
+
+
+
+

Three-Concept Hierarchy (WriteStream / WriteCloser / WriteSink)

+
+

A three-level hierarchy was considered, with an intermediate concept (WriteCloser or similar) requiring write_some + write_eof but not write. This was rejected because the intermediate concept serves no practical purpose: any concrete type that has write_some and write_eof can and should provide write. There is no use case where a type offers partial writes and EOF signaling but cannot offer complete writes.

+
+
+
+
+
+

Summary

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionContractUse Case

write_some(buffers)

Writes one or more bytes. May consume less than the full sequence.

Relay interiors, backpressure, implementing composed algorithms.

write(buffers)

Writes the entire buffer sequence.

Protocol messages, serialization, structured output.

write_eof(buffers)

Writes the entire buffer sequence and signals EOF atomically.

Final chunk of a relay, last fragment of serialized output.

write_eof()

Signals EOF without data.

When the final data was already written separately.

+
+

WriteSink refines WriteStream. The write_now algorithm operates on any WriteStream and provides complete-write behavior with eager completion and frame caching, but it cannot replicate the atomic write_eof(buffers) that WriteSink enables.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8h.BufferSink.html b/preview/8.design/8h.BufferSink.html new file mode 100644 index 0000000..ab5e433 --- /dev/null +++ b/preview/8.design/8h.BufferSink.html @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + + BufferSink Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

BufferSink Concept Design

+
+

Overview

+
+
+

This document describes the design of the BufferSink concept, the rationale behind each member function, and the relationship between BufferSink, WriteSink, and the pull_from algorithm. BufferSink models the "callee owns buffers" pattern: the sink provides writable memory and the caller writes directly into it, enabling zero-copy data transfer.

+
+
+

Where WriteSink requires the caller to supply buffer sequences containing the data to be written, BufferSink inverts the ownership: the sink exposes its internal storage and the caller fills it in place. The two concepts are independent — neither refines the other — but the type-erased wrapper any_buffer_sink satisfies both, bridging the two patterns behind a single runtime interface.

+
+
+
+
+

Concept Definition

+
+
+
+
template<typename T>
+concept BufferSink =
+    requires(T& sink, std::span<mutable_buffer> dest, std::size_t n)
+    {
+        // Synchronous: get writable buffers from sink's internal storage
+        { sink.prepare(dest) } -> std::same_as<std::span<mutable_buffer>>;
+
+        // Async: commit n bytes written
+        { sink.commit(n) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(sink.commit(n)),
+            std::error_code>;
+
+        // Async: commit n final bytes and signal end of data
+        { sink.commit_eof(n) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(sink.commit_eof(n)),
+            std::error_code>;
+    };
+
+
+
+

BufferSink is a standalone concept. It does not refine WriteSink or WriteStream. The two concept families model different ownership patterns and can coexist on the same concrete type.

+
+
+
+
+

Caller vs Callee Buffer Ownership

+
+
+

The library provides two concept families for writing data:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectWriteSink (caller owns)BufferSink (callee owns)

Buffer origin

Caller allocates and fills buffers, then passes them to the sink.

Sink exposes its internal storage; caller writes into it.

Copy cost

One copy: caller’s buffer → sink’s internal storage (or I/O submission).

Zero copies when the sink’s internal storage is the final destination + (e.g., a ring buffer, kernel page, or DMA region).

API shape

write_some(buffers), write(buffers), write_eof(buffers)

prepare(dest), commit(n), commit_eof(n)

Natural for

Protocol serializers that produce data into their own buffers, then hand + it off.

Sinks backed by pre-allocated memory (ring buffers, memory-mapped files, + hardware DMA descriptors).

+
+

Both patterns are necessary. A compression sink, for example, naturally owns the output buffer where compressed data lands; the caller feeds uncompressed data and the compressor writes results directly into the ring buffer. Conversely, an HTTP serializer naturally produces header bytes into its own scratch space and then hands the buffer sequence to a WriteSink.

+
+
+
+
+

Member Functions

+
+
+

prepare(dest) — Expose Writable Buffers

+
+

Fills the provided span with mutable buffer descriptors pointing to the sink’s internal storage. This operation is synchronous.

+
+
+

Signature

+
+
+
std::span<mutable_buffer> prepare(std::span<mutable_buffer> dest);
+
+
+
+
+

Semantics

+
+
    +
  • +

    Returns a (possibly empty) subspan of dest populated with buffer descriptors. Each descriptor points to a writable region of the sink’s internal storage.

    +
  • +
  • +

    If the returned span is empty, the sink has no available space. The caller should call commit (possibly with n == 0) to flush buffered data and then retry prepare.

    +
  • +
  • +

    The returned buffers remain valid until the next call to prepare, commit, commit_eof, or until the sink is destroyed.

    +
  • +
+
+
+
+

Why Synchronous

+
+

prepare is synchronous because it is a bookkeeping operation: the sink returns pointers into memory it already owns. No I/O or blocking is involved. Making prepare asynchronous would force a coroutine suspension on every iteration of the write loop, adding overhead with no benefit.

+
+
+

When the sink has no available space, the correct response is to commit the pending data (which is asynchronous, as it may trigger I/O), then call prepare again. This keeps the synchronous fast path free of unnecessary suspensions.

+
+
+
+

Why a Span Parameter

+
+

The caller provides the output span rather than the sink returning a fixed-size container. This lets the caller control the stack allocation and avoids heap allocation for the buffer descriptor array:

+
+
+
+
mutable_buffer arr[16];
+auto bufs = sink.prepare(arr);
+
+
+
+

The sink fills as many descriptors as it can (up to dest.size()) and returns the populated subspan.

+
+
+
+
+

commit(n) — Finalize Written Data

+
+

Commits n bytes that the caller wrote into the buffers returned by the most recent prepare. Returns (error_code).

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec.

    +
  • +
  • +

    On error: ec.

    +
  • +
  • +

    May trigger underlying I/O (flush to socket, compression pass, etc.).

    +
  • +
  • +

    After commit, the buffers returned by the prior prepare are invalidated. The caller must call prepare again before writing more data.

    +
  • +
+
+
+
+

When to Use

+
+
    +
  • +

    After writing data into prepared buffers and needing to continue the transfer.

    +
  • +
  • +

    To flush when prepare returns an empty span (call commit(0) to drain the sink’s internal buffer and free space).

    +
  • +
+
+
+
+
+

commit_eof(n) — Commit Final Data and Signal EOF

+
+

Commits n bytes written to the most recent prepare buffers and signals end-of-stream. Returns (error_code).

+
+
+

After a successful call, no further prepare, commit, or commit_eof operations are permitted.

+
+
+

Semantics

+
+
    +
  • +

    On success: !ec. The sink is finalized.

    +
  • +
  • +

    On error: ec. The sink state is unspecified.

    +
  • +
+
+
+
+

Why commit_eof Takes a Byte Count

+
+

Combining the final commit with the EOF signal in a single operation enables the same optimizations that motivate write_eof(buffers) on the WriteSink side:

+
+
+
    +
  • +

    HTTP chunked encoding: commit_eof(n) can emit the data chunk followed by the terminal 0\r\n\r\n in a single system call.

    +
  • +
  • +

    Compression (deflate): commit_eof(n) can pass Z_FINISH to the final deflate() call, producing the compressed data and the stream trailer together.

    +
  • +
  • +

    TLS close-notify: commit_eof(n) can coalesce the final application data with the TLS close-notify alert.

    +
  • +
+
+
+

A separate commit(n) followed by commit_eof(0) would prevent these optimizations because the sink cannot know during commit that no more data will follow.

+
+
+
+
+
+
+

Relationship to pull_from

+
+
+

pull_from is a composed algorithm that transfers data from a ReadSource (or ReadStream) into a BufferSink. It is the callee-owns-buffers counterpart to push_to, which transfers from a BufferSource to a WriteSink.

+
+
+
+
template<ReadSource Src, BufferSink Sink>
+io_task<std::size_t>
+pull_from(Src& source, Sink& sink);
+
+template<ReadStream Src, BufferSink Sink>
+io_task<std::size_t>
+pull_from(Src& source, Sink& sink);
+
+
+
+

The algorithm loops:

+
+
+
    +
  1. +

    Call sink.prepare(arr) to get writable buffers.

    +
  2. +
  3. +

    Call source.read(bufs) (or source.read_some(bufs)) to fill them.

    +
  4. +
  5. +

    Call sink.commit(n) to finalize the data.

    +
  6. +
  7. +

    When the source signals EOF, call sink.commit_eof(0) to finalize the sink.

    +
  8. +
+
+
+

pull_from is the right tool when the data source satisfies ReadSource or ReadStream and the destination satisfies BufferSink. It avoids the intermediate caller-owned buffer that a WriteSink-based transfer would require.

+
+
+

The two pull_from overloads differ in how they read from the source:

+
+ ++++ + + + + + + + + + + + + + + + + +
OverloadBehavior

pull_from(ReadSource, BufferSink)

Uses source.read(bufs) for complete reads. Each iteration fills the + prepared buffers entirely (or returns EOF/error).

pull_from(ReadStream, BufferSink)

Uses source.read_some(bufs) for partial reads. Each iteration + commits whatever data was available, providing lower latency.

+
+
+
+

Relationship to WriteSink

+
+
+

BufferSink and WriteSink are independent concepts serving different ownership models. A concrete type may satisfy one, the other, or both.

+
+
+

The type-erased wrapper any_buffer_sink satisfies both concepts. When the wrapped type satisfies only BufferSink, the WriteSink operations (write_some, write, write_eof) are synthesized from prepare and commit with a buffer_copy step. When the wrapped type satisfies both BufferSink and WriteSink, the native write operations are forwarded directly through the virtual boundary with no extra copy.

+
+
+

This dual-concept bridge lets algorithms constrained on WriteSink work with any BufferSink through any_buffer_sink, and lets algorithms constrained on BufferSink work natively with the callee-owns-buffers pattern.

+
+
+

Transfer Algorithm Matrix

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SourceSinkAlgorithm

BufferSource

WriteSink

push_to — pulls from source, writes to sink

BufferSource

WriteStream

push_to — pulls from source, writes partial to stream

ReadSource

BufferSink

pull_from — prepares sink buffers, reads into them

ReadStream

BufferSink

pull_from — prepares sink buffers, reads partial into them

+
+
+
+
+

Use Cases

+
+
+

Zero-Copy Transfer

+
+

When the sink’s internal storage is the final destination (a ring buffer, a kernel page, a DMA region), the caller writes directly into it with no intermediate copy.

+
+
+
+
template<BufferSink Sink>
+task<> fill_sink(Sink& sink, std::string_view data)
+{
+    std::size_t written = 0;
+    while(written < data.size())
+    {
+        mutable_buffer arr[16];
+        auto bufs = sink.prepare(arr);
+        if(bufs.empty())
+        {
+            auto [ec] = co_await sink.commit(0);
+            if(ec)
+                co_return;
+            continue;
+        }
+
+        std::size_t n = buffer_copy(
+            bufs,
+            const_buffer(
+                data.data() + written,
+                data.size() - written));
+        written += n;
+
+        if(written == data.size())
+        {
+            auto [ec] = co_await sink.commit_eof(n);
+            if(ec)
+                co_return;
+        }
+        else
+        {
+            auto [ec] = co_await sink.commit(n);
+            if(ec)
+                co_return;
+        }
+    }
+}
+
+
+
+
+

Transferring from a ReadSource

+
+

The pull_from algorithm reads data directly into the sink’s buffers, avoiding a caller-owned intermediate buffer entirely.

+
+
+
+
template<ReadSource Source, BufferSink Sink>
+task<> transfer(Source& source, Sink& sink)
+{
+    auto [ec, total] = co_await pull_from(source, sink);
+    if(ec)
+        co_return;
+    // total bytes transferred with zero intermediate copies
+}
+
+
+
+

Compare with the WriteSink approach, which requires an intermediate buffer:

+
+
+
+
template<ReadStream Source, WriteSink Sink>
+task<> transfer(Source& source, Sink& sink)
+{
+    char buf[8192];  // intermediate buffer
+    for(;;)
+    {
+        auto [ec, n] = co_await source.read_some(
+            mutable_buffer(buf));
+        if(ec == cond::eof)
+        {
+            auto [wec] = co_await sink.write_eof();
+            co_return;
+        }
+        if(ec)
+            co_return;
+        auto [wec, nw] = co_await sink.write(
+            const_buffer(buf, n));
+        if(wec)
+            co_return;
+    }
+}
+
+
+
+

The BufferSink path eliminates the buf[8192] intermediate buffer.

+
+
+
+

HTTP Response Body Sink

+
+

An HTTP response body can be consumed through a BufferSink interface. The concrete implementation handles transfer encoding behind the abstraction.

+
+
+
+
task<> receive_body(
+    any_buffer_sink& body,
+    ReadSource auto& source)
+{
+    auto [ec, n] = co_await pull_from(source, body);
+    if(ec)
+        co_return;
+    // Body fully received and committed
+}
+
+
+
+

The caller does not know whether the body uses content-length, chunked encoding, or compression. The BufferSink interface handles the difference.

+
+
+
+

Compression Pipeline

+
+

A compression sink owns an output ring buffer where compressed data lands. The caller writes uncompressed data into prepared buffers, and commit triggers a compression pass.

+
+
+
+
template<BufferSink Sink>
+task<> compress_input(Sink& sink, std::span<const char> input)
+{
+    std::size_t pos = 0;
+    while(pos < input.size())
+    {
+        mutable_buffer arr[16];
+        auto bufs = sink.prepare(arr);
+        if(bufs.empty())
+        {
+            auto [ec] = co_await sink.commit(0);
+            if(ec)
+                co_return;
+            continue;
+        }
+
+        std::size_t n = buffer_copy(
+            bufs,
+            const_buffer(input.data() + pos,
+                         input.size() - pos));
+        pos += n;
+
+        auto [ec] = co_await sink.commit(n);
+        if(ec)
+            co_return;
+    }
+    auto [ec] = co_await sink.commit_eof(0);
+    if(ec)
+        co_return;
+}
+
+
+
+

The commit_eof(0) call lets the compression sink pass Z_FINISH to the final deflate call, flushing the compressed stream trailer.

+
+
+
+

Bridging to WriteSink via any_buffer_sink

+
+

When a function is constrained on WriteSink but the concrete type satisfies only BufferSink, any_buffer_sink bridges the gap.

+
+
+
+
template<WriteSink Sink>
+task<> send_message(Sink& sink, std::string_view msg);
+
+// Concrete type satisfies BufferSink only
+my_ring_buffer ring;
+any_buffer_sink abs(ring);
+
+// Works: any_buffer_sink satisfies WriteSink
+co_await send_message(abs, "hello");
+
+
+
+

When the wrapped type also satisfies WriteSink, any_buffer_sink forwards the native write operations directly, avoiding the synthesized prepare + buffer_copy + commit path.

+
+
+
+
+
+

Alternatives Considered

+
+
+

Combined Prepare-and-Commit

+
+

An alternative design combined the prepare and commit steps into a single asynchronous operation: write(dest) → (error_code, span), where the sink returns writable buffers and the commit happens on the next call. This was rejected because:

+
+
+
    +
  • +

    The synchronous prepare is a pure bookkeeping operation. Making it asynchronous forces a coroutine suspension on every iteration, even when the sink has space available.

    +
  • +
  • +

    Separating prepare from commit lets the caller fill multiple prepared buffers before incurring the cost of an asynchronous commit.

    +
  • +
  • +

    The two-step protocol makes the buffer lifetime explicit: buffers from prepare are valid until commit or commit_eof.

    +
  • +
+
+
+
+

prepare Returning a Count Instead of a Span

+
+

An earlier design had prepare fill a raw pointer array and return a count (std::size_t prepare(mutable_buffer* arr, std::size_t max)). This was replaced by the span-based interface because:

+
+
+
    +
  • +

    std::span<mutable_buffer> is self-describing: it carries both the pointer and the size, eliminating a class of off-by-one errors.

    +
  • +
  • +

    Returning a subspan of the input span is idiomatic C++ and composes well with range-based code.

    +
  • +
  • +

    The raw-pointer interface required two parameters (pointer + count) where the span interface requires one.

    +
  • +
+
+
+
+

Separate flush Operation

+
+

A design with an explicit flush method (distinct from commit) was considered, where commit would only buffer data and flush would trigger I/O. This was rejected because:

+
+
+
    +
  • +

    It adds a fourth operation to the concept without clear benefit. The commit operation already serves both roles: it finalizes the caller’s data and may trigger I/O at the sink’s discretion.

    +
  • +
  • +

    A sink that wants to defer I/O can do so internally by accumulating committed data and flushing when its buffer is full. The caller does not need to know when physical I/O occurs.

    +
  • +
  • +

    Adding flush would complicate the pull_from algorithm, which would need to decide when to call flush versus commit.

    +
  • +
+
+
+
+

BufferSink Refining WriteSink

+
+

A design where BufferSink refined WriteSink (requiring all types to implement both interfaces) was considered. This was rejected because:

+
+
+
    +
  • +

    Many natural BufferSink types (ring buffers, DMA descriptors) have no meaningful write_some primitive. Their data path is prepare-then-commit, not write-from-caller-buffer.

    +
  • +
  • +

    Requiring write_some, write, and write_eof on every BufferSink would force implementations to synthesize these operations even when they are never called.

    +
  • +
  • +

    The any_buffer_sink wrapper provides the bridge when needed, without burdening every concrete type.

    +
  • +
+
+
+
+
+
+

Summary

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionContractUse Case

prepare(dest)

Synchronous. Fills span with writable buffer descriptors from the + sink’s internal storage. Returns empty span if no space is available.

Every write iteration: obtain writable memory before filling it.

commit(n)

Async. Commits n bytes to the sink. May trigger I/O.

Interior iterations of a transfer loop.

commit_eof(n)

Async. Commits n bytes and signals end-of-stream. Finalizes the sink.

Final iteration: deliver last data and close the stream.

+
+

BufferSink is the callee-owns-buffers counterpart to WriteSink. The pull_from algorithm transfers data from a ReadSource or ReadStream into a BufferSink, and any_buffer_sink bridges the two patterns by satisfying both BufferSink and WriteSink behind a single type-erased interface.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8i.TypeEraseAwaitable.html b/preview/8.design/8i.TypeEraseAwaitable.html new file mode 100644 index 0000000..61ba345 --- /dev/null +++ b/preview/8.design/8i.TypeEraseAwaitable.html @@ -0,0 +1,591 @@ + + + + + + + + + + + + + + Type-Erasing Awaitables :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Type-Erasing Awaitables

+
+

Overview

+
+
+

The any_* wrappers type-erase stream and source concepts so that algorithms can operate on heterogeneous concrete types through a uniform interface. Each wrapper preallocates storage for the type-erased awaitable at construction time, achieving zero steady-state allocation.

+
+
+

Two vtable layouts are used depending on how many operations the wrapper exposes.

+
+
+
+
+

Single-Operation: Flat Vtable

+
+
+

When a wrapper exposes exactly one async operation (e.g. any_read_stream with read_some, or any_write_stream with write_some), all function pointers live in a single flat vtable:

+
+
+
+
// Flat vtable -- 64 bytes, one cache line
+struct vtable
+{
+    void (*construct_awaitable)(...);       // 8
+    bool (*await_ready)(void*);            // 8
+    std::coroutine_handle<> (*await_suspend)(void*, ...);     // 8
+    io_result<size_t> (*await_resume)(void*); // 8
+    void (*destroy_awaitable)(void*);      // 8
+    size_t awaitable_size;                 // 8
+    size_t awaitable_align;                // 8
+    void (*destroy)(void*);                // 8
+};
+
+
+
+

The inner awaitable can be constructed in either await_ready or await_suspend, depending on whether the outer awaitable has a short-circuit path.

+
+
+

Construct in await_ready (any_read_stream)

+
+

When there is no outer short-circuit, constructing in await_ready lets immediate completions skip await_suspend entirely:

+
+
+
+
bool await_ready() {
+    vt_->construct_awaitable(stream_, storage_, buffers);
+    awaitable_active_ = true;
+    return vt_->await_ready(storage_);   // true → no suspend
+}
+
+std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, io_env const* env) {
+    return vt_->await_suspend(storage_, h, env);
+}
+
+io_result<size_t> await_resume() {
+    auto r = vt_->await_resume(storage_);
+    vt_->destroy_awaitable(storage_);
+    awaitable_active_ = false;
+    return r;
+}
+
+
+
+
+

Construct in await_suspend (any_write_stream)

+
+

When the outer awaitable has a short-circuit (empty buffers), construction is deferred to await_suspend so the inner awaitable is never created on the fast path:

+
+
+
+
bool await_ready() const noexcept {
+    return buffers_.empty();             // short-circuit, no construct
+}
+
+std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, io_env const* env) {
+    vt_->construct_awaitable(stream_, storage_, buffers);
+    awaitable_active_ = true;
+    if(vt_->await_ready(storage_))
+        return h;                        // immediate → resume caller
+    return vt_->await_suspend(storage_, h, env);
+}
+
+io_result<size_t> await_resume() {
+    if(!awaitable_active_)
+        return {{}, 0};                  // short-circuited
+    auto r = vt_->await_resume(storage_);
+    vt_->destroy_awaitable(storage_);
+    awaitable_active_ = false;
+    return r;
+}
+
+
+
+

Both variants touch the same two cache lines on the hot path.

+
+
+
+
+
+

Multi-Operation: Split Vtable with awaitable_ops

+
+
+

When a wrapper exposes multiple operations that produce different awaitable types (e.g. any_read_source with read_some and read, or any_write_sink with write_some, write, write_eof(buffers), and write_eof()), a split layout is required. Each construct call returns a pointer to a static constexpr awaitable_ops matching the awaitable it created.

+
+
+
+
// Per-awaitable dispatch -- 32 bytes
+struct awaitable_ops
+{
+    bool (*await_ready)(void*);
+    std::coroutine_handle<> (*await_suspend)(void*, ...);
+    io_result<size_t> (*await_resume)(void*);
+    void (*destroy)(void*);
+};
+
+// Vtable -- 32 bytes
+struct vtable
+{
+    awaitable_ops const* (*construct_awaitable)(...);
+    size_t awaitable_size;
+    size_t awaitable_align;
+    void (*destroy)(void*);
+};
+
+
+
+

The inner awaitable is constructed in await_suspend. Outer await_ready handles short-circuits (e.g. empty buffers) before the inner type is ever created:

+
+
+
+
bool await_ready() const noexcept {
+    return buffers_.empty();             // short-circuit
+}
+
+std::coroutine_handle<> await_suspend(std::coroutine_handle<> h, io_env const* env) {
+    active_ops_ = vt_->construct_awaitable(stream_, storage_, buffers_);
+    if(active_ops_->await_ready(storage_))
+        return h;                        // immediate → resume caller
+    return active_ops_->await_suspend(storage_, h, env);
+}
+
+io_result<size_t> await_resume() {
+    if(!active_ops_)
+        return {{}, 0};                  // short-circuited
+    auto r = active_ops_->await_resume(storage_);
+    active_ops_->destroy(storage_);
+    active_ops_ = nullptr;
+    return r;
+}
+
+
+
+
+
+

Cache Line Analysis

+
+
+

Immediate completion path — inner await_ready returns true:

+
+
+
+
Flat (any_read_stream, any_write_stream): 2 cache lines
+  LINE 1  object        stream_, vt_, cached_awaitable_, ...
+  LINE 2  vtable        construct → await_ready → await_resume → destroy
+                         (contiguous, sequential access, prefetch-friendly)
+
+Split (any_read_source, any_write_sink):  3 cache lines
+  LINE 1  object        source_, vt_, cached_awaitable_, active_ops_, ...
+  LINE 2  vtable        construct_awaitable
+  LINE 3  awaitable_ops await_ready → await_suspend → await_resume → destroy
+                         (separate .rodata address, defeats spatial prefetch)
+
+
+
+

The flat layout keeps all per-awaitable function pointers adjacent to construct_awaitable in a single 64-byte structure. The split layout places vtable and awaitable_ops at unrelated addresses in .rodata, adding one cache miss on the hot path.

+
+
+
+
+

When to Use Which

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
Flat vtableSplit vtable

Wrapper has exactly one async operation

Wrapper has multiple async operations

any_read_stream (read_some)

any_read_source (read_some, read)

any_write_stream (write_some)

any_write_sink (write_some, write, write_eof(bufs), write_eof())

+
+
+
+

Why the Flat Layout Cannot Scale

+
+
+

With multiple operations, each construct call produces a different concrete awaitable type. The per-awaitable function pointers (await_ready, await_suspend, await_resume, destroy) must match the type that was constructed. The split layout solves this by returning the correct awaitable_ops const* from each construct call. The flat layout would require duplicating all four function pointers in the vtable for every operation — workable for two operations, unwieldy for four.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8j.any_buffer_sink.html b/preview/8.design/8j.any_buffer_sink.html new file mode 100644 index 0000000..df65c22 --- /dev/null +++ b/preview/8.design/8j.any_buffer_sink.html @@ -0,0 +1,799 @@ + + + + + + + + + + + + + + any_buffer_sink Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

any_buffer_sink Design

+
+

Overview

+
+
+

This document describes the design of any_buffer_sink, a type-erased wrapper that satisfies both BufferSink and WriteSink. The central design goal is to serve two fundamentally different data-production patterns through a single runtime interface, with no performance compromise for either.

+
+
+

Data producers fall into two categories:

+
+
+
    +
  • +

    Generators produce data on demand. They do not hold the data in advance; they compute or serialize it into memory that someone else provides. An HTTP header serializer, a JSON encoder, and a compression engine are generators.

    +
  • +
  • +

    Buffered sources already have data sitting in buffers. A memory-mapped file, a ring buffer that received data from a socket, and a pre-serialized response body are buffered sources.

    +
  • +
+
+
+

These two patterns require different buffer ownership models. Generators need writable memory from the sink (the BufferSink pattern). Buffered sources need to hand their existing buffers to the sink (the WriteSink pattern). Forcing either pattern through the other’s interface introduces an unnecessary copy.

+
+
+

any_buffer_sink exposes both interfaces. The caller chooses the one that matches how its data is produced. The wrapper dispatches to the underlying concrete sink through the optimal path, achieving zero-copy when the concrete type supports it and falling back to a synthesized path when it does not.

+
+
+
+
+

The Two Interfaces

+
+
+

BufferSink: Callee-Owned Buffers

+
+

The BufferSink interface (prepare, commit, commit_eof) is designed for generators. The sink owns the memory. The generator asks for writable space, fills it, and commits:

+
+
+
+
any_buffer_sink abs(concrete_sink{});
+
+mutable_buffer arr[16];
+auto bufs = abs.prepare(arr);
+// serialize directly into bufs
+auto [ec] = co_await abs.commit(bytes_written);
+
+
+
+

The data lands in the sink’s internal storage with no intermediate copy. If the concrete sink is backed by a kernel page, a DMA descriptor, or a ring buffer, the bytes go directly to their final destination.

+
+
+
+

WriteSink: Caller-Owned Buffers

+
+

The WriteSink interface (write_some, write, write_eof) is designed for buffered sources. The caller already has the data in buffers and passes them to the sink:

+
+
+
+
any_buffer_sink abs(concrete_sink{});
+
+// Data already in buffers -- pass them directly
+auto [ec, n] = co_await abs.write(existing_buffers);
+
+// Or atomically write and signal EOF
+auto [ec2, n2] = co_await abs.write_eof(final_buffers);
+
+
+
+

When the concrete sink natively supports WriteSink, the caller’s buffers propagate directly through the type-erased boundary. The sink receives the original buffer descriptors pointing to the caller’s memory. No data is copied into an intermediate staging area.

+
+
+
+
+
+

Dispatch Strategy

+
+
+

The vtable records whether the wrapped concrete type satisfies WriteSink in addition to BufferSink. This determination is made at compile time when the vtable is constructed. At runtime, each WriteSink operation checks a single nullable function pointer to select its path.

+
+
+

Native Forwarding (BufferSink + WriteSink)

+
+

When the concrete type satisfies both concepts, the WriteSink vtable slots are populated with functions that construct the concrete type’s own write_some, write, write_eof(buffers), and write_eof() awaitables in the cached storage. The caller’s buffer descriptors pass straight through:

+
+
+
+
caller buffers → vtable → concrete write(buffers) → I/O
+
+
+
+

No prepare, no buffer_copy, no commit. The concrete type receives the caller’s buffers and can submit them directly to the operating system, the compression library, or the next pipeline stage.

+
+
+

This is the zero-copy path for buffered sources writing to a sink that natively accepts caller-owned buffers.

+
+
+
+

Synthesized Path (BufferSink Only)

+
+

When the concrete type satisfies only BufferSink, the WriteSink vtable slots are null. The wrapper synthesizes the WriteSink operations from the BufferSink primitives:

+
+
+
+
caller buffers → prepare → buffer_copy → commit → I/O
+
+
+
+

For write_some:

+
+
+
    +
  1. +

    Call prepare to get writable space from the sink.

    +
  2. +
  3. +

    Copy data from the caller’s buffers into the prepared space with buffer_copy.

    +
  4. +
  5. +

    Call commit to finalize.

    +
  6. +
+
+
+

For write and write_eof: the same loop, repeated until all data is consumed. write_eof finishes with commit_eof to signal end-of-stream.

+
+
+

This path incurs one buffer copy, which is unavoidable: the concrete sink only knows how to accept data through its own prepare/commit protocol, so the caller’s buffers must be copied into the sink’s internal storage.

+
+
+
+
+
+

Why This Matters

+
+
+

No Compromise

+
+

A naive design would pick one interface and synthesize the other unconditionally. If the wrapper only exposed BufferSink, every buffered source would pay a copy to move its data into the sink’s prepared buffers. If the wrapper only exposed WriteSink, every generator would need to allocate its own intermediate buffer, fill it, then hand it to the sink — paying a copy that the BufferSink path avoids.

+
+
+

any_buffer_sink avoids both penalties. Each data-production pattern uses the interface designed for it. The only copy that occurs is the one that is structurally unavoidable: when a WriteSink operation targets a concrete type that only speaks BufferSink.

+
+
+
+

True Zero-Copy for Buffered Sources

+
+

Consider an HTTP server where the response body is a memory-mapped file. The file’s pages are already in memory. Through the WriteSink interface, those pages can propagate directly to the underlying transport:

+
+
+
+
// body_source is a BufferSource backed by mmap pages
+// response_sink wraps a concrete type satisfying both concepts
+
+any_buffer_sink response_sink(&concrete);
+
+const_buffer arr[16];
+for(;;)
+{
+    auto [ec, bufs] = co_await body_source.pull(arr);
+    if(ec == cond::eof)
+    {
+        auto [ec2] = co_await response_sink.write_eof();
+        break;
+    }
+    if(ec)
+        break;
+    // bufs point directly into mmap pages
+    // write() propagates them through the vtable to the concrete sink
+    auto [ec2, n] = co_await response_sink.write(bufs);
+    if(ec2)
+        break;
+    body_source.consume(n);
+}
+
+
+
+

The mapped pages flow from body_source.pull through response_sink.write to the concrete transport with no intermediate copy. If the concrete sink can scatter-gather those buffers into a writev system call, the data moves from the page cache to the network card without touching user-space memory a second time.

+
+
+
+

Generators Write In-Place

+
+

An HTTP header serializer generates bytes on the fly. It does not hold the output in advance. Through the BufferSink interface, it writes directly into whatever memory the concrete sink provides:

+
+
+
+
task<> serialize_headers(
+    any_buffer_sink& sink,
+    response const& resp)
+{
+    mutable_buffer arr[16];
+
+    for(auto const& field : resp.fields())
+    {
+        auto bufs = sink.prepare(arr);
+        // serialize field directly into bufs
+        std::size_t n = format_field(bufs, field);
+        auto [ec] = co_await sink.commit(n);
+        if(ec)
+            co_return;
+    }
+    // headers done; body follows through the same sink
+}
+
+
+
+

The serializer never allocates a scratch buffer for the formatted output. The bytes land directly in the sink’s internal storage, which might be a chunked-encoding buffer, a TLS record buffer, or a circular buffer feeding a socket.

+
+
+
+
+
+

Awaitable Caching

+
+
+

any_buffer_sink uses the split vtable pattern described in Type-Erasing Awaitables. Multiple async operations (commit, commit_eof, plus the four WriteSink operations when the concrete type supports them) share a single cached awaitable storage region.

+
+
+

The constructor computes the maximum size and alignment across all awaitable types that the concrete type can produce and allocates that storage once. This reserves all virtual address space at construction time, so memory usage is measurable at server startup rather than growing piecemeal as requests arrive.

+
+
+

Two separate awaitable_ops structs are used:

+
+
+
    +
  • +

    awaitable_ops for operations yielding io_result<> (commit, commit_eof, write_eof())

    +
  • +
  • +

    write_awaitable_ops for operations yielding io_result<std::size_t> (write_some, write, write_eof(buffers))

    +
  • +
+
+
+

Each construct_* function in the vtable creates the concrete awaitable in the cached storage and returns a pointer to the matching static constexpr ops table. The wrapper stores this pointer as active_ops_ or active_write_ops_ and uses it for await_ready, await_suspend, await_resume, and destruction.

+
+
+
+
+

Ownership Modes

+
+
+

Owning

+
+
+
any_buffer_sink abs(my_concrete_sink{args...});
+
+
+
+

The wrapper allocates storage for the concrete sink and moves it in. The wrapper owns the sink and destroys it in its destructor. The awaitable cache is allocated separately.

+
+
+

If either allocation fails, the constructor cleans up via an internal guard and propagates the exception.

+
+
+
+

Non-Owning (Reference)

+
+
+
my_concrete_sink sink;
+any_buffer_sink abs(&sink);
+
+
+
+

The wrapper stores a pointer without allocating storage for the sink. The concrete sink must outlive the wrapper. Only the awaitable cache is allocated.

+
+
+

This mode is useful when the concrete sink is managed by a higher-level object (e.g., an HTTP connection that owns the transport) and the wrapper is a short-lived handle passed to a body-production function.

+
+
+
+
+
+

Relationship to any_buffer_source

+
+
+

any_buffer_source is the read-side counterpart, satisfying both BufferSource and ReadSource. The same dual-interface principle applies in mirror image:

+
+ +++++ + + + + + + + + + + + + + + + + + + + +
DirectionPrimary conceptSecondary concept

Writing (any_buffer_sink)

BufferSink (callee-owned)

WriteSink (caller-owned)

Reading (any_buffer_source)

BufferSource (callee-owned)

ReadSource (caller-owned)

+
+

Both wrappers enable the same design philosophy: the caller chooses the interface that matches its data-production or data-consumption pattern, and the wrapper dispatches optimally.

+
+
+
+
+

Alternatives Considered

+
+
+

WriteSink-Only Wrapper

+
+

A design where the type-erased wrapper satisfied only WriteSink was considered. Generators would allocate their own scratch buffer, serialize into it, and call write. This was rejected because:

+
+
+
    +
  • +

    Every generator pays a buffer copy that the BufferSink path avoids. For high-throughput paths (HTTP header serialization, compression output), this copy is measurable.

    +
  • +
  • +

    Generators must manage scratch buffer lifetime and sizing. The prepare/commit protocol pushes this responsibility to the sink, which knows its own buffer topology.

    +
  • +
  • +

    The commit_eof(n) optimization (coalescing final data with stream termination) is lost. A generator calling write cannot signal that its last write is the final one without a separate write_eof() call, preventing the sink from combining them.

    +
  • +
+
+
+
+

BufferSink-Only Wrapper

+
+

A design where the wrapper satisfied only BufferSink was considered. Buffered sources would copy their data into the sink’s prepared buffers via prepare + buffer_copy + commit. This was rejected because:

+
+
+
    +
  • +

    Every buffered source pays a copy that native WriteSink forwarding avoids. When the source is a memory-mapped file and the sink is a socket, this eliminates the zero-copy path entirely.

    +
  • +
  • +

    The buffer_copy step becomes the bottleneck for large transfers, dominating what would otherwise be a pure I/O operation.

    +
  • +
  • +

    Buffered sources that produce scatter-gather buffer sequences (multiple non-contiguous regions) must copy each region individually into prepared buffers, losing the ability to pass the entire scatter-gather list to a writev system call.

    +
  • +
+
+
+
+

Separate Wrapper Types

+
+

A design with two distinct wrappers (any_buffer_sink satisfying only BufferSink and any_write_sink satisfying only WriteSink) was considered. The caller would choose which wrapper to construct based on its data-production pattern. This was rejected because:

+
+
+
    +
  • +

    The caller and the sink are often decoupled. An HTTP server framework provides the sink; the user provides the body producer. The framework cannot know at compile time whether the user will call prepare/commit or write/write_eof.

    +
  • +
  • +

    Requiring two wrapper types forces the framework to either pick one (losing the other pattern) or expose both (complicating the API).

    +
  • +
  • +

    A single wrapper that satisfies both concepts lets the framework hand one object to the body producer, which uses whichever interface is natural. No choice is imposed on the framework or the user.

    +
  • +
+
+
+
+

Always Synthesizing WriteSink

+
+

A design where the WriteSink operations were always synthesized from prepare + buffer_copy + commit, even when the concrete type natively supports WriteSink, was considered. This would simplify the vtable by removing the nullable write-forwarding slots. This was rejected because:

+
+
+
    +
  • +

    The buffer copy is measurable. For a concrete type that can accept caller-owned buffers directly (e.g., a socket wrapper with writev support), the synthesized path adds a copy that native forwarding avoids.

    +
  • +
  • +

    The write_eof(buffers) atomicity guarantee is lost. The synthesized path must decompose it into prepare + buffer_copy + commit_eof, which the concrete type cannot distinguish from a non-final commit followed by an empty commit_eof. This prevents optimizations like coalescing the last data chunk with a chunked-encoding terminator.

    +
  • +
+
+
+
+
+
+

Summary

+
+
+

any_buffer_sink satisfies both BufferSink and WriteSink behind a single type-erased interface. The dual API lets each data-production pattern use the interface designed for it:

+
+ +++++ + + + + + + + + + + + + + + + + + + + +
Producer typeInterfaceData path

Generator (produces on demand)

prepare / commit / commit_eof

Writes directly into sink’s internal storage. Zero copy.

Buffered source (data already in memory)

write_some / write / write_eof

Buffers propagate through the vtable. Zero copy when the concrete + type natively supports WriteSink. One copy (synthesized) when + it does not.

+
+

The dispatch is determined at construction time through nullable vtable slots. At runtime, a single pointer check selects the native or synthesized path. Neither pattern pays for the other’s existence.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8k.Executor.html b/preview/8.design/8k.Executor.html new file mode 100644 index 0000000..7bcb69d --- /dev/null +++ b/preview/8.design/8k.Executor.html @@ -0,0 +1,947 @@ + + + + + + + + + + + + + + Executor Concept Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Executor Concept Design

+
+

Overview

+
+
+

This document describes the design of the Executor concept: the interface through which coroutines are scheduled for execution. It explains the relationship to Asio’s executor model, why dispatch returns void, why defer was dropped, how executor_ref achieves zero-allocation type erasure, and the I/O completion pattern that motivates the entire design.

+
+
+

The Executor concept exists to answer one question: when a coroutine is ready to run, where does it run? The concept captures the rules for scheduling coroutine resumption, tracking outstanding work for graceful shutdown, and accessing the execution context that owns the executor. Every I/O awaitable in Corosio — sockets, acceptors, timers, resolvers — depends on this concept to dispatch completions back to the correct executor.

+
+
+
+
+

Definition

+
+
+
+
template<class E>
+concept Executor =
+    std::is_nothrow_copy_constructible_v<E> &&
+    std::is_nothrow_move_constructible_v<E> &&
+    requires(E& e, E const& ce, E const& ce2,
+             std::coroutine_handle<> h)
+    {
+        { ce == ce2 } noexcept -> std::convertible_to<bool>;
+        { ce.context() } noexcept;
+        requires std::is_lvalue_reference_v<
+            decltype(ce.context())> &&
+            std::derived_from<
+                std::remove_reference_t<
+                    decltype(ce.context())>,
+                execution_context>;
+        { ce.on_work_started() } noexcept;
+        { ce.on_work_finished() } noexcept;
+
+        { ce.dispatch(h) };
+        { ce.post(h) };
+    };
+
+
+
+

An Executor provides exactly two operations on a coroutine handle:

+
+
+

dispatch(h) — Execute If Safe

+
+

If the executor determines it is safe (e.g., the current thread is already associated with the executor’s context), resumes the coroutine inline via h.resume(). Otherwise, posts the coroutine for later execution. Returns void.

+
+
+
+

post(h) — Always Queue

+
+

Queues the coroutine for later execution without ever executing it inline. Never blocks. Use when guaranteed asynchrony is required.

+
+
+

The remaining operations support context access, lifecycle management, and identity:

+
+
+
+

context() — Access the Execution Context

+
+

Returns an lvalue reference to the execution_context that created this executor. The context provides service infrastructure, frame allocators, and shutdown coordination.

+
+
+
+

on_work_started() / on_work_finished() — Track Work

+
+

Paired calls that track outstanding work. When the count reaches zero, the context’s event loop (run()) returns. These calls must be balanced: each on_work_started must have a matching on_work_finished.

+
+
+
+

operator== — Equality Comparison

+
+

Two executors are equal if they submit work to the same destination. This enables the same-executor optimization: when a completion’s executor matches the caller’s, the dispatch can skip the indirection.

+
+
+
+
+
+

Relationship to Asio

+
+
+

Kohlhoff’s Asio library established the executor-as-policy model that Capy inherits. As described in P0113R0:

+
+
+
+
+

An executor is to function execution as an allocator is to +allocation.

+
+
+
+
+

Capy retains the core elements of this model:

+
+
+
    +
  • +

    Work tracking. on_work_started / on_work_finished for graceful shutdown.

    +
  • +
  • +

    dispatch / post duality. Execute-if-safe versus always-queue.

    +
  • +
  • +

    execution_context base class. Service infrastructure and context lifetime management.

    +
  • +
  • +

    Equality comparison. Same-executor optimization.

    +
  • +
+
+
+

Capy removes or changes:

+
+
+
    +
  • +

    defer. Dropped entirely. See Why Two Operations, Not Three.

    +
  • +
  • +

    Function object submission. Asio executors accept arbitrary callables. Capy executors accept only std::coroutine_handle<>. This removes the need for allocator-aware function erasure and enables a simpler, cheaper type-erased wrapper (executor_ref).

    +
  • +
  • +

    dispatch return type. Asio’s dispatch returns void for the same reason Capy’s does, but Capy also considered and rejected a coroutine_handle<> return for symmetric transfer. See Why dispatch Returns void.

    +
  • +
+
+
+

The result is a concept that preserves Asio’s proven execution model while removing the machinery that a coroutine-native library does not need.

+
+
+
+
+

Why dispatch Returns void

+
+
+

An earlier design had dispatch return std::coroutine_handle<> so that callers could use it for symmetric transfer from await_suspend. This was rejected because it violates a fundamental constraint of the I/O layer.

+
+
+

The Problem: Synchronous Completion During await_suspend

+
+

When an I/O awaitable initiates an operation inside await_suspend, the I/O might complete immediately. If it does, the completion path would call dispatch(h) while the caller’s await_suspend is still on the call stack. If dispatch resumed the coroutine inline via h.resume(), the coroutine would execute while await_suspend has not yet returned — resuming a coroutine from inside await_suspend before the suspension machinery completes risks undefined behavior.

+
+
+

The C++ standard describes the sequencing in [expr.await/5.1]:

+
+
+
+
+

If the result of await-ready is false, the coroutine is +considered suspended. Then, await-suspend is evaluated.

+
+
+
+
+

Although the standard considers the coroutine suspended before await_suspend is called, resuming it from within await_suspend creates a nested resumption on the same call stack. The resumed coroutine runs, potentially suspends again or completes, and then control returns into the middle of await_suspend. If the coroutine was destroyed during resumption, await_suspend returns into a destroyed frame.

+
+
+
+

Why I/O Awaitables Return void or std::noop_coroutine()

+
+

To avoid this, all I/O awaitables return void or std::noop_coroutine() from await_suspend. Both forms guarantee that the caller is fully suspended and the call stack has unwound before any completion handler can resume the coroutine. The I/O operation is initiated during await_suspend, but the completion is dispatched later — from the event loop, after await_suspend has returned.

+
+
+

P0913R1 introduced the coroutine_handle<Z> return type for symmetric transfer, which is the correct mechanism for coroutine-to-coroutine control transfer (as used by task<T> internally). But I/O awaitables cannot use it because the I/O completion is asynchronous relative to await_suspend — it comes from the reactor or proactor, not from the awaitable itself.

+
+
+
+

Consequence for dispatch

+
+

Since the primary consumer of dispatch is I/O completion — called after the coroutine is suspended, from the event loop — dispatch does not need to participate in symmetric transfer. It calls h.resume() inline when safe and returns void. A conforming implementation looks like:

+
+
+
+
void dispatch(std::coroutine_handle<> h) const
+{
+    if(ctx_.running_in_this_thread())
+        h.resume();
+    else
+        post(h);
+}
+
+
+
+

After dispatch returns, the state of h is unspecified. The coroutine may have completed, been destroyed, or suspended at a different point. Callers must not use h after calling dispatch.

+
+
+
+
+
+

Why Two Operations, Not Three

+
+
+

Asio provides three submission methods: dispatch, post, and defer. Capy provides only dispatch and post.

+
+
+

What defer Does

+
+

P0113R0 describes defer:

+
+
+
+
+

A defer operation is similar to a post operation…​ However, a +defer operation also implies a relationship between the caller +and the function object being submitted. It is intended for use +when submitting a function object that represents a continuation +of the caller.

+
+
+
+
+

The optimization this enables is thread-local queuing. When the caller is already executing within the executor’s context, defer saves the continuation to a thread-local queue instead of the shared work queue. From P0113R0:

+
+
+
+
+

If the caller is executing within the thread pool, saves the +function object to a thread-local queue. Once control returns to +the thread pool, the function object is scheduled for execution +as soon as possible.

+
+
+
+
+
+

Why Coroutines Make defer Redundant

+
+

In a callback-based library, when an asynchronous operation completes, the completion handler must be submitted to the executor as a function object. If the handler is the caller’s continuation, defer tells the executor "this is my next step; optimize accordingly."

+
+
+

In a coroutine-native library, this optimization is provided by the language itself. P0913R1 introduced symmetric transfer specifically to eliminate the need for queues and schedulers in coroutine-to-coroutine control transfer:

+
+
+
+
+

Currently Coroutines TS only supports asymmetric control transfer +where suspend always returns control back to the current +coroutine caller or resumer. In order to emulate symmetric +coroutine to coroutine control transfer, one needs to build a +queue and a scheduler.

+
+
+
+
+

When task<T>::await_suspend returns the parent’s coroutine handle, the compiler performs a tail-call-like transfer directly to the parent. No queue, no executor submission, no defer. The optimization that defer provides through a runtime hint, symmetric transfer provides through a compile-time guarantee.

+
+
+

Corosio confirms this in practice: its entire I/O layer — sockets, acceptors, timers, resolvers, signals — across all three backends (epoll, IOCP, select) uses only dispatch and post. No code path requires defer.

+
+
+
+
+
+

Why std::coroutine_handle<>, Not Typed Handles

+
+
+

The executor accepts std::coroutine_handle<> — the type-erased handle — rather than std::coroutine_handle<P> for a specific promise type P.

+
+
+

This decision has three consequences:

+
+
+
    +
  • +

    Type erasure is possible. executor_ref wraps any executor behind a uniform interface. If dispatch and post were templated on the promise type, the vtable would need to be generic over all promise types, making type erasure impractical.

    +
  • +
  • +

    Executor implementations are independent of coroutine internals. An executor schedules resumption. It does not need to know what the coroutine’s promise type is, what value it produces, or how it handles exceptions. The type-erased handle provides exactly the right interface: resume() and nothing else.

    +
  • +
  • +

    I/O operation structures stay simple. Every pending I/O operation in Corosio stores two fields: std::coroutine_handle<> h (a typedef for std::coroutine_handle<>) and capy::executor_ref ex. Both are type-erased. The operation structure does not need to be templated on the coroutine’s promise type, which keeps the I/O backend code non-generic and out of headers.

    +
  • +
+
+
+
+
+

Why Nothrow Copy and Move

+
+
+

The concept requires std::is_nothrow_copy_constructible_v<E> and std::is_nothrow_move_constructible_v<E>.

+
+
+

Executors propagate through coroutine machinery at points where exceptions cannot be handled: inside await_suspend, during promise construction, and through type-erased wrappers like executor_ref. An exception thrown from an executor copy at any of these points would leave the coroutine in an unrecoverable state — suspended but with no executor to resume it through.

+
+
+

The nothrow requirement eliminates this failure mode entirely. In practice, executors are lightweight handles — a pointer to the execution context and perhaps a strand pointer or a priority value. Nothrow copy and move are natural for such types. The requirement does not impose a burden; it documents what is already true of every reasonable executor implementation.

+
+
+
+
+

Work Tracking, Shutdown, and Executor Validity

+
+
+

The on_work_started and on_work_finished operations serve three roles.

+
+
+

Event Loop Lifetime

+
+

Work tracking is the mechanism by which the event loop knows when to stop. When outstanding work reaches zero, run() returns. This is not bookkeeping — it is the event loop’s termination signal.

+
+
+

In Corosio, on_work_finished triggers stop() when the atomic work count reaches zero:

+
+
+
+
void on_work_finished() noexcept
+{
+    if(outstanding_work_.fetch_sub(
+        1, std::memory_order_acq_rel) == 1)
+        stop();
+}
+
+
+
+

Every run_async call increments the count. When the launched task completes, the count decrements. When no tasks remain, run() returns. Without work tracking in the executor, the event loop would need a separate signaling mechanism or would spin indefinitely.

+
+
+
+

Public Visibility

+
+

These operations are public, not private with friendship. The reason is extensibility: work_guard is the library’s RAII wrapper for work tracking, but users may define their own guards with additional behaviors (logging, metrics, timeout detection). Making work tracking private would require the library to grant friendship to types it cannot anticipate.

+
+
+
+

Executor Validity

+
+

An executor becomes invalid when its context’s shutdown() returns. After shutdown:

+
+
+
    +
  • +

    dispatch, post, on_work_started, on_work_finished: undefined behavior.

    +
  • +
  • +

    Copy, comparison, context(): valid until the context is destroyed.

    +
  • +
+
+
+

This two-phase model exists because shutdown drains outstanding work. During the drain, executors must still be copyable (they are stored in pending operations) and comparable (for same-executor checks). Only the work-submission operations become invalid, because the context has stopped accepting new work.

+
+
+
+
+
+

Why context() Returns execution_context&

+
+
+

The context() operation returns a reference to the execution_context base class, not the concrete derived type.

+
+
+

This serves two purposes:

+
+
+
    +
  • +

    Type erasure. executor_ref can wrap any executor without knowing its context type. If context() returned a concrete type, the vtable would need a different return type per executor type.

    +
  • +
  • +

    Service lookup. The execution_context base class provides use_service<T>() and make_service<T>(), which is sufficient for all runtime service discovery. I/O objects do not need the concrete context type to find their services.

    +
  • +
+
+
+

Corosio demonstrates this pattern throughout its public API. I/O objects accept any executor and extract the context via the base class reference:

+
+
+
+
template<class Ex>
+    requires capy::Executor<Ex>
+explicit tcp_socket(Ex const& ex)
+    : tcp_socket(ex.context())
+{
+}
+
+
+
+

The socket constructor receives execution_context& and looks up the socket service. The concrete context type — epoll_context, iocp_context, select_context — is irrelevant to the socket.

+
+
+
+
+

The executor_ref Design

+
+
+

executor_ref is a non-owning, type-erased wrapper for any executor satisfying the Executor concept. It is the mechanism by which I/O operations store and use executors without templates.

+
+
+

Two Pointers

+
+

The entire object is two pointers:

+
+
+
+
class executor_ref
+{
+    void const* ex_;                       // pointer to the executor
+    detail::executor_vtable const* vt_;    // pointer to the vtable
+};
+
+
+
+

Two pointers fit in two registers. executor_ref can be passed by value as cheaply as passing a pointer. No heap allocation, no small-buffer optimization, no reference counting.

+
+
+
+

Why Not std::function or std::any

+
+

std::function and small-buffer-optimized type erasure wrappers have overhead that executor usage cannot tolerate:

+
+
+
    +
  • +

    Heap allocation. std::function may allocate when the callable exceeds the SBO threshold. Executor dispatch happens on every I/O completion — allocation on the hot path is unacceptable.

    +
  • +
  • +

    Reference counting. std::shared_ptr-based wrappers add atomic reference count operations on every copy. Executors are copied frequently as they propagate through coroutine chains.

    +
  • +
  • +

    Indirection. SBO wrappers store either inline data or a heap pointer, adding a branch on every operation.

    +
  • +
+
+
+

executor_ref avoids all three. The vtable pointer goes directly to a static constexpr structure in .rodata. One indirection, no branches, no allocation.

+
+
+
+

Why Not C++ Virtual Functions

+
+

C++ virtual dispatch places the vtable pointer inside each heap-allocated object. Every virtual call chases a pointer from the object to its vtable, which may reside at an unpredictable address in memory. When objects of different types are interleaved on the heap, their vtable pointers point to different locations in .rodata, defeating spatial prefetch and polluting the instruction cache.

+
+
+

executor_ref separates the vtable from the object. The vtable is a static constexpr structure — one per executor type, shared by all instances of that type. Because most programs use only one or two executor types (a thread pool executor and perhaps a strand), the vtable stays hot in L1 cache. The executor pointer and the vtable pointer sit adjacent in the executor_ref object, so both are loaded in a single cache line.

+
+
+
+

Reference Semantics

+
+

executor_ref stores a pointer to the executor, not a copy. The executor must outlive the executor_ref. This matches how executors propagate through coroutine chains: the executor is owned by the execution context (which outlives all coroutines running on it), and executor_ref is a lightweight handle passed through await_suspend and stored in I/O operation structures.

+
+
+
+
+
+

The I/O Completion Pattern

+
+
+

The executor concept is designed around a single use case: I/O completion dispatch. This pattern is the reason the concept exists.

+
+
+

Capture at Initiation

+
+

When a coroutine co_await`s an I/O awaitable, the awaitable’s `await_suspend receives the caller’s executor and stores it as executor_ref:

+
+
+
+
template<typename Ex>
+auto await_suspend(
+    std::coroutine_handle<> h,
+    Ex const& ex) -> std::coroutine_handle<>
+{
+    // ex is captured as executor_ref in the operation
+    return socket_.connect(h, ex, endpoint_, token_, &ec_);
+}
+
+
+
+

The operation structure stores both the coroutine handle and the executor reference:

+
+
+
+
struct io_op : scheduler_op
+{
+    std::coroutine_handle<> h;
+    capy::executor_ref ex;
+    // ... error codes, buffers, etc.
+};
+
+
+
+
+

Dispatch at Completion

+
+

When the I/O completes (from the reactor thread for epoll, the completion port for IOCP, or the select loop), the operation uses the stored executor to resume the coroutine:

+
+
+
+
void operator()() override
+{
+    // ... set error codes ...
+    capy::executor_ref saved_ex(std::move(ex));
+    std::coroutine_handle<> saved_h(std::move(h));
+    impl_ptr.reset();
+    saved_ex.dispatch(saved_h);
+}
+
+
+
+

dispatch checks whether the current thread is already running on the executor’s context. If so, the coroutine resumes inline. If not, the coroutine is posted for later execution on the correct context.

+
+
+
+

Platform Independence

+
+

This pattern is identical across all three Corosio backends: epoll (Linux), IOCP (Windows), and select (POSIX fallback). The executor concept and executor_ref provide the abstraction that makes this possible. The backend-specific code deals with I/O readiness or completion notification. The executor-specific code deals with coroutine scheduling. The two concerns are cleanly separated.

+
+
+
+
+
+

Why Not std::execution (P2300)

+
+
+

P2300 defines a sender/receiver model where execution context flows backward from receiver to sender via queries after connect():

+
+
+
+
task<int> async_work();              // Frame allocated NOW
+auto sndr = async_work();
+auto op = connect(sndr, receiver);   // Allocator available NOW
+start(op);                           //   -- too late
+
+
+
+

For coroutines, this ordering is fatal. Coroutine frame allocation happens before the coroutine body executes. The compiler calls operator new first, then constructs the promise, then begins execution. Any mechanism that provides the allocator after the coroutine call — receiver queries, await_transform, explicit method calls — arrives after the frame is already allocated with the wrong (or default) allocator.

+
+
+

Capy’s model flows context forward from launcher to task. The run_async(ex, alloc)(my_task()) two-phase invocation sets the thread-local allocator before the task expression is evaluated, so operator new reads it in time. This is described in detail in Run API.

+
+
+

The same forward-flowing model applies to executors. The launcher binds the executor before the task runs. The task’s promise stores the executor and propagates it to nested awaitables via await_transform. Context flows from caller to callee at every level, never backward.

+
+
+
+
+

Conforming Signatures

+
+
+

A minimal executor implementation:

+
+
+
+
class my_executor
+{
+public:
+    execution_context& context() const noexcept;
+
+    void on_work_started() const noexcept;
+    void on_work_finished() const noexcept;
+
+    void dispatch(std::coroutine_handle<> h) const;
+    void post(std::coroutine_handle<> h) const;
+
+    bool operator==(my_executor const&) const noexcept;
+};
+
+
+
+
+
+

Summary

+
+
+

The Executor concept provides dispatch and post for coroutine scheduling, work tracking for event loop lifetime, and context() for service access. The design descends from Asio’s executor model but is adapted for coroutines: defer is replaced by symmetric transfer, function objects are replaced by std::coroutine_handle<>, and dispatch returns void because I/O completions are dispatched after suspension, not during it.

+
+
+

executor_ref type-erases any executor into two pointers, enabling platform-independent I/O completion dispatch with zero allocation and predictable cache behavior. The capture-at-initiation / dispatch-at-completion pattern is the fundamental use case the concept serves.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8l.RunApi.html b/preview/8.design/8l.RunApi.html new file mode 100644 index 0000000..c45218f --- /dev/null +++ b/preview/8.design/8l.RunApi.html @@ -0,0 +1,852 @@ + + + + + + + + + + + + + + Run API Design :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Run API Design

+
+

Overview

+
+
+

This document explains the naming conventions and call syntax of the two launcher functions: run_async (fire-and-forget from non-coroutine code) and run (awaitable within a coroutine). Both accept any type satisfying IoRunnable — not just task<T> — and use a deliberate two-phase invocation pattern — f(context)(task) — that exists for a mechanical reason rooted in coroutine frame allocation timing.

+
+
+
+
+

Usage

+
+
+

run_async — Fire-and-Forget Launch

+
+

run_async launches any IoRunnable from non-coroutine code: main(), callback handlers, event loops. task<T> is the most common conforming type, but any user-defined type satisfying the concept works. The function does not return a value to the caller. Handlers receive the task’s result or exception after completion.

+
+
+
+
// Executor only (uses default recycling allocator)
+run_async(ex)(my_task());
+
+// With a stop token for cooperative cancellation
+std::stop_source source;
+run_async(ex, source.get_token())(cancellable_task());
+
+// With a custom memory resource
+run_async(ex, my_pool)(my_task());
+
+// With a result handler
+run_async(ex, [](int result) {
+    std::cout << "Got: " << result << "\n";
+})(compute_value());
+
+// With separate success and error handlers
+run_async(ex,
+    [](int result) { std::cout << "Got: " << result << "\n"; },
+    [](std::exception_ptr ep) { /* handle error */ }
+)(compute_value());
+
+// Full: executor, stop_token, allocator, success handler, error handler
+run_async(ex, st, alloc, h1, h2)(my_task());
+
+
+
+
+

run — Awaitable Launch Within a Coroutine

+
+

run is the coroutine-side counterpart. It binds any IoRunnable to a (possibly different) executor and returns the result to the caller via co_await. It also supports overloads that customize stop token or allocator while inheriting the caller’s executor.

+
+
+
+
// Switch to a different executor for CPU-bound work
+task<void> parent()
+{
+    int result = co_await run(worker_ex)(compute_on_worker());
+    // Completion returns to parent's executor
+}
+
+// Customize stop token, inherit caller's executor
+task<void> with_timeout()
+{
+    std::stop_source source;
+    co_await run(source.get_token())(subtask());
+}
+
+// Customize allocator, inherit caller's executor
+task<void> with_custom_alloc()
+{
+    co_await run(my_alloc)(subtask());
+}
+
+// Switch executor AND customize allocator
+task<void> full_control()
+{
+    co_await run(worker_ex, my_alloc)(cpu_bound_task());
+}
+
+
+
+
+

run_async on a Strand

+
+

A common pattern for launching per-connection coroutines on a strand, ensuring serialized access to connection state:

+
+
+
+
void on_accept(tcp::socket sock)
+{
+    strand my_strand(ioc.get_executor());
+    run_async(my_strand)(handle_connection(std::move(sock)));
+}
+
+
+
+
+
+
+

Alternatives Considered

+
+
+

Several alternative naming and syntax proposals were evaluated and discarded. The following table shows each rejected form alongside the chosen form.

+
+
+

Builder Pattern: on / with / spawn / call

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RejectedChosen

capy::on(ex).spawn(t)

run_async(ex)(t)

co_await capy::on(ex).call(t)

co_await run(ex)(t)

co_await capy::with(st).call(t)

co_await run(st)(t)

co_await capy::with(alloc).call(t)

co_await run(alloc)(t)

capy::on(ex).block(t)

test::run_blocking(ex)(t)

+
+

What this looks like in practice:

+
+
+
+
// Rejected: builder pattern
+capy::on(ex).spawn(my_task());
+co_await capy::on(worker_ex).call(compute());
+co_await capy::with(my_alloc).call(subtask());
+
+// Chosen: two-phase invocation
+run_async(ex)(my_task());
+co_await run(worker_ex)(compute());
+co_await run(my_alloc)(subtask());
+
+
+
+

The builder pattern reads well as English, but it creates problems in C++ practice. See Why Not a Builder Pattern below for the full analysis.

+
+
+
+

Single-Call with Named Method

+
+
+
// Rejected: single-call
+run_async(ex, my_task());
+
+
+
+

This fails the allocator timing constraint entirely. The task argument my_task() is evaluated before run_async can set the thread-local allocator. The coroutine frame is allocated with the wrong (or no) allocator. This is not a style preference — it is a correctness bug.

+
+
+
+

Named Method on Wrapper

+
+
+
// Rejected: named method instead of operator()
+run_async(ex).spawn(my_task());
+co_await run(ex).call(compute());
+
+
+
+

This preserves the two-phase timing guarantee and avoids the namespace collision problems of on/with. The objection is minor: .spawn() and .call() add vocabulary without adding clarity. The wrapper already has exactly one purpose — accepting a task. A named method implies the wrapper has a richer interface than it does. operator() is the conventional C++ way to express "this object does exactly one thing." That said, this alternative has legs and could be revisited if the ()() syntax proves too confusing in practice.

+
+
+
+
+
+

The Names

+
+
+

Why run

+
+

The run prefix was chosen for several reasons:

+
+
+
    +
  • +

    Greppability. Searching for run_async( or run( in a codebase produces unambiguous results. Short, common English words like on or with collide with local variable names, parameter names, and other libraries. A using namespace capy; combined with a local variable named on produces silent shadowing bugs.

    +
  • +
  • +

    Verb clarity. run tells you what happens: something executes. run_async tells you it executes without waiting. run inside a coroutine tells you control transfers and returns. Prepositions like on and with say nothing about the action — they are sentence fragments waiting for a verb.

    +
  • +
  • +

    Discoverability. The run_* family groups together in documentation, autocompletion, and alphabetical listings. Users searching for "how do I launch a task" find run_async and run as a coherent pair.

    +
  • +
  • +

    Consistency. The naming follows the established pattern from io_context::run(), std::jthread, and other C++ APIs where run means "begin executing work."

    +
  • +
  • +

    No false promises. A builder-pattern syntax like on(ex).spawn(t) implies composability — on(ex).with(alloc).call(t) — that the API does not deliver. The f(x)(t) pattern is honest about being exactly two steps, no more. It does not invite users to chain methods that do not exist.

    +
  • +
+
+
+
+

Why Not a Builder Pattern

+
+

An alternative proposal suggested replacing the two-call syntax with a builder-style API:

+
+
+
+
// Rejected builder pattern
+capy::on(ex).spawn(my_task());
+co_await capy::on(ex).call(compute());
+co_await capy::with(st).call(subtask());
+co_await capy::with(alloc).call(subtask());
+capy::on(ex).block(my_task());
+
+
+
+

While the English readability of on(ex).spawn(t) is genuinely appealing, the approach has practical problems in a Boost library:

+
+
+
    +
  • +

    Namespace pollution. on and with are among the most common English words in programming. In a Boost library used alongside dozens of other namespaces, these names invite collisions. Consider what happens with using namespace capy;:

    +
    +
    +
    int on = 42;                  // local variable
    +on(ex).spawn(my_task());      // ambiguous: variable or function?
    +
    +void handle(auto with) {      // parameter name
    +    with(alloc).call(sub());  // won't compile
    +}
    +
    +
    +
    +

    + The names run and run_async do not have this problem. No one names their variables run_async.

    +
    +
  • +
  • +

    Semantic ambiguity. with(st) versus with(alloc) — with what, exactly? The current API uses run(st) and run(alloc) where overload resolution disambiguates naturally because the verb run provides context. A bare preposition provides none.

    +
    +
    +
    // What does "with" mean here? Stop token or allocator?
    +co_await capy::with(x).call(subtask());
    +
    +// "run" provides a verb -- the argument type disambiguates
    +co_await run(x)(subtask());
    +
    +
    +
  • +
  • +

    Builder illusion. Dot-chaining suggests composability that does not exist. Users will naturally try:

    +
    +
    +
    // These look reasonable but don't work
    +capy::on(ex).with(alloc).call(my_task());
    +capy::on(ex).with(st).with(alloc).spawn(my_task(), h1, h2);
    +
    +
    +
    +

    + The current syntax makes the interface boundary explicit: the first call captures all context, the second call accepts the task. There is no dot-chain to extend.

    +
    +
  • +
  • +

    Erases the test boundary. run_blocking lives in capy::test deliberately — it is a test utility, not a production API. The proposed on(ex).block(t) places it alongside .spawn() and .call() as if it were a first-class production method. That is a promotion this API has not earned.

    +
  • +
  • +

    Hidden critical ordering. The two-phase invocation exists for a mechanical reason (allocator timing, described below). With on(ex).spawn(t), the critical sequencing guarantee is buried behind what looks like a casual method call. The ()() syntax is pedagogically valuable — it signals that something important happens in two distinct steps.

    +
  • +
  • +

    Overload count does not shrink. run_async has 18 overloads for good reason (executor x stop_token x allocator x handlers). The builder pattern still needs all those combinations — they just move from free function overloads to constructor or method overloads. The complexity does not vanish; it relocates.

    +
  • +
+
+
+
+
+
+

The Two-Phase Invocation

+
+
+

The Problem: Allocator Timing

+
+

Coroutine frame allocation happens before the coroutine body executes. When the compiler encounters a coroutine call, it:

+
+
+
    +
  1. +

    Calls operator new to allocate the frame

    +
  2. +
  3. +

    Constructs the promise object

    +
  4. +
  5. +

    Begins execution of the coroutine body

    +
  6. +
+
+
+

Any mechanism that injects the allocator after the call — receiver queries, await_transform, explicit method calls — arrives too late. The frame is already allocated.

+
+
+

This is the fundamental tension identified in D4003 �3.3:

+
+
+
+
+

The allocator must be present at invocation. Coroutine frame +allocation has a fundamental timing constraint: operator new +executes before the coroutine body. When a coroutine is called, +the compiler allocates the frame first, then begins execution. +Any mechanism that injects context later — receiver connection, +await_transform, explicit method calls — arrives too late.

+
+
+
+
+
+

The Solution: C++17 Postfix Evaluation Order

+
+

C++17 guarantees that in a postfix-expression call, the postfix-expression is sequenced before the argument expressions:

+
+
+
+
+

The postfix-expression is sequenced before each expression in +the expression-list and any default argument. — [expr.call]

+
+
+
+
+

In the expression run_async(ex)(my_task()):

+
+
+
    +
  1. +

    run_async(ex) evaluates first. This returns a wrapper object (run_async_wrapper) whose constructor calls set_current_frame_allocator() — storing a thread-local pointer to the memory resource.

    +
  2. +
  3. +

    my_task() evaluates second. The coroutine’s operator new reads the thread-local pointer and allocates the frame from it.

    +
  4. +
  5. +

    operator() on the wrapper takes ownership of the task and dispatches it to the executor.

    +
  6. +
+
+
+
+
// Step 1: wrapper constructor sets TLS allocator
+//         v~~~~~~~~~~~~~~v
+   run_async(ex, alloc)    (my_task());
+//                          ^~~~~~~~~^
+// Step 2: task frame allocated using TLS allocator
+
+
+
+

This sequencing is not an implementation detail — it is the only correct way to inject an allocator into a coroutine’s frame allocation when the allocator is not known at compile time.

+
+
+
+

How It Works in the Code

+
+

The run_async_wrapper constructor sets the thread-local allocator:

+
+
+
+
run_async_wrapper(Ex ex, std::stop_token st, Handlers h, Alloc a)
+    : tr_(detail::make_trampoline<Ex, Handlers, Alloc>(
+        std::move(ex), std::move(h), std::move(a)))
+    , st_(std::move(st))
+{
+    // Set TLS before task argument is evaluated
+    set_current_frame_allocator(tr_.h_.promise().get_resource());
+}
+
+
+
+

The task’s operator new reads it:

+
+
+
+
static void* operator new(std::size_t size)
+{
+    auto* mr = get_current_frame_allocator();
+    if(!mr)
+        mr = std::pmr::get_default_resource();
+    return mr->allocate(size, alignof(std::max_align_t));
+}
+
+
+
+

The wrapper is and its operator() is rvalue-ref-qualified, preventing misuse:

+
+
+
+
// Correct: wrapper is a temporary, used immediately
+run_async(ex)(my_task());
+
+// Compile error: cannot call operator() on an lvalue
+auto w = run_async(ex);
+w(my_task());  // Error: requires rvalue
+
+
+
+
+

The run Variant

+
+

The run function uses the same two-phase pattern inside coroutines. An additional subtlety arises: the wrapper is a temporary that dies before co_await suspends the caller. The wrapper’s frame_memory_resource would be destroyed before the child task executes.

+
+
+

The solution is to store a copy of the allocator in the awaitable returned by operator(). Since standard allocator copies are equivalent — memory allocated with one copy can be deallocated with another — this preserves correctness while keeping the allocator alive for the task’s duration.

+
+
+
+

Comparison with std::execution

+
+

In std::execution (P2300), context flows backward from receiver to sender via queries after connect():

+
+
+
+
task<int> async_work();              // Frame allocated NOW
+auto sndr = async_work();
+auto op = connect(sndr, receiver);   // Allocator available NOW -- too late
+start(op);
+
+
+
+

In the IoAwaitable model, context flows forward from launcher to task:

+
+
+
+
1. Set TLS allocator     -->  2. Call task()
+                               3. operator new (uses TLS)
+                               4. await_suspend
+
+
+
+

The allocator is ready before the frame is created. No query machinery can retroactively fix an allocation that already happened.

+
+
+
+
+
+

Summary

+
+ ++++ + + + + + + + + + + +

run_async(ctx)(task)

Fire-and-forget launch from non-coroutine code

co_await run(ctx)(task)

Awaitable launch within a coroutine

+
+

The run name is greppable, unambiguous, and won’t collide with local variables in a namespace-heavy Boost codebase. The f(ctx)(task) syntax exists because coroutine frame allocation requires the allocator to be set before the task expression is evaluated, and C++17 postfix sequencing guarantees exactly that ordering. The syntax is intentionally explicit about its two steps — it tells the reader that something important happens between them.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8m.WhyNotCobalt.html b/preview/8.design/8m.WhyNotCobalt.html new file mode 100644 index 0000000..e6d1032 --- /dev/null +++ b/preview/8.design/8m.WhyNotCobalt.html @@ -0,0 +1,1391 @@ + + + + + + + + + + + + + + Capy and Boost.Cobalt: A Comparison :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Capy and Boost.Cobalt: A Comparison

+
+
+
+

Both libraries use C++20 coroutines for asynchronous programming. The differences begin with the foundation.

+
+
+

Cobalt is a coroutine layer built on Boost.Asio. It adds coroutine syntax — promise, task, generator — on top of Asio’s existing I/O infrastructure. Asio is not coroutines-only. It supports callbacks, futures, and coroutines equally. Cobalt inherits this foundation. It can add coroutine types on top, but it cannot change what lies beneath.

+
+
+

Capy is a coroutine-native I/O foundation designed from the ground up. The design started from the ideal use case and worked backward to the implementation. The concept hierarchy, the type-erased wrappers, the allocator model — these fell out naturally from use-case-first design, without compromise.

+
+
+
+
+

The Dimovian Ideal

+
+
+

An I/O library should make the implementation completely invisible to its consumers. Public headers declare the interface — types, functions, contracts. All platform-specific machinery lives in the translation unit. No implementation detail leaks into the consumer’s code.

+
+
+

Capy achieves the Dimovian Ideal. The proof is in example/asio/.

+
+
+

The Header

+
+

api/capy_streams.hpp is the public interface. It contains zero Asio includes:

+
+
+
+
#include <boost/capy/ex/execution_context.hpp>
+#include <boost/capy/ex/executor_ref.hpp>
+#include <boost/capy/io/any_stream.hpp>
+
+#include <utility>
+
+namespace boost { namespace asio { class io_context; } }
+
+class asio_context : public capy::execution_context
+{
+    struct impl;
+    impl* impl_;
+
+public:
+    using executor_type = capy::executor_ref;
+
+    asio_context();
+    ~asio_context();
+
+    net::io_context& context() noexcept;
+    executor_type get_executor() noexcept;
+    void run();
+};
+
+std::pair<capy::any_stream, capy::any_stream>
+make_stream_pair(asio_context& ctx);
+
+
+
+

Asio appears only as a forward declaration. The context uses pimpl. The factory returns capy::any_stream — a type-erased stream that hides the concrete socket type entirely.

+
+
+
+

The Translation Unit

+
+

api/capy_streams.cpp is where every Asio header lives. The concrete asio_socket wraps tcp::socket. The concrete asio_executor wraps io_context::executor_type. All of it is invisible to consumers of the header.

+
+
+
+

The Algorithm Code

+
+

any_stream.cpp demonstrates the result. It includes api/capy_streams.hpp and Capy headers. No Asio headers. None.

+
+
+
+
capy::task<>
+writer(capy::any_stream& stream, std::size_t total)
+{
+    char buf[128];
+    std::memset(buf, 'X', sizeof(buf));
+
+    std::size_t written = 0;
+    while(written < total)
+    {
+        std::size_t chunk = (std::min)(sizeof(buf), total - written);
+        auto [ec, n] = co_await stream.write_some(
+            capy::make_buffer(buf, chunk));
+        if(ec)
+            co_return;
+        written += n;
+    }
+}
+
+capy::task<>
+reader(capy::any_stream& stream, std::size_t total)
+{
+    char buf[128];
+
+    std::size_t read_total = 0;
+    while(read_total < total)
+    {
+        auto [ec, n] = co_await stream.read_some(
+            capy::make_buffer(buf));
+        if(ec)
+            co_return;
+        read_total += n;
+    }
+}
+
+
+
+

writer() and reader() operate on capy::any_stream&. They don’t know what I/O backend produced the stream. They never need to know.

+
+
+
+

What Cobalt Does Instead

+
+

Cobalt’s cobalt::io namespace provides wrappers around Asio I/O objects. These wrappers expose concrete Asio types through their interfaces. A cobalt::io::steady_timer is an asio::basic_waitable_timer. A cobalt::io::socket is an asio::basic_stream_socket. The wrappers preserve direct access to the underlying Asio types.

+
+
+

Consumers of Cobalt I/O objects must include Asio headers. The backend remains part of the public interface.

+
+
+
+ +
+

A library written against Capy’s type-erased streams can be relinked against entirely different stream implementations. TCP today. QUIC tomorrow. A test mock in CI. The polymorphism is the same as what templated Asio code achieves — except the library does not need a recompile. The binary is the interface. Drop in a new .so or .dll that implements the stream contract, relink, and behavior changes.

+
+
+

Templates can achieve this by type-erasing every customization point. The cost makes it impractical.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

Backend includes in header

None (forward declaration only)

Required

Implementation hiding

Pimpl + type-erased returns

Concrete Asio types exposed

Algorithm code depends on backend

No

Yes

Relink without recompile

Yes

No

ABI stability across implementations

Yes

No

+
+
+
+
+

Stream Concepts

+
+
+

Capy defines seven coroutine-only stream concepts. Cobalt inherits Asio’s AsyncReadStream and AsyncWriteStream, which are hybrid concepts supporting callbacks, futures, and coroutines. Cobalt’s cobalt::io wrappers simplify the API and Cobalt defines stream abstractions (write_stream, read_stream, stream) as abstract base classes, a distinct approach from Capy’s concept-based hierarchy. Cobalt’s wrappers still include full Asio headers. See Write Stream Design for a detailed comparison of the two approaches.

+
+
+

Capy’s concepts form a refinement hierarchy that emerged naturally from use-case-first design:

+
+
+
+
  ReadStream                WriteStream
+  (partial reads)           (partial writes)
+       |                         |
+       v                         v
+  ReadSource                WriteSink
+  (complete reads)          (complete writes + EOF)
+
+
+  BufferSource              BufferSink
+  (zero-copy pull)          (zero-copy prepare/commit)
+
+
+
+

BufferSource and BufferSink implement callee-owns-buffers I/O. The source provides buffers; the caller processes them in place. No copies. Memory-mapped files, hardware DMA buffers, and kernel-provided memory all work naturally through this pattern.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConceptCapyCobalt

ReadStream

Yes

WriteStream

Yes

Stream

Yes

ReadSource

Yes

WriteSink

Yes

BufferSource

Yes

BufferSink

Yes

+
+
+
+

Type-Erased Streams

+
+
+

Traditional approaches to type erasure in Asio focus on the lowest-level elements: the completion handler, the executor, the allocator. This is not the right layer. Type-erasing these individually adds overhead at every customization point while still leaving the stream type concrete and visible.

+
+
+

Capy type-erases the stream itself. This is possible because coroutines provide structural type erasure — the continuation is always a handle, not a template parameter. When the library is coroutines-only, one virtual call per I/O operation is the total cost. The completion handler, executor, and allocator do not need individual erasure because they are not part of the stream’s operation signature.

+
+
+

Cobalt defines stream abstractions (write_stream, read_stream, stream) as abstract base classes in cobalt/io/stream.hpp, taking a different approach from Capy’s concept + type-erased wrapper model. See Write Stream Design for a side-by-side analysis.

+
+
+

The wrappers compose. any_buffer_source also satisfies ReadSource — natively if the wrapped type supports both, synthesized otherwise. any_buffer_sink also satisfies WriteSink. You pick the abstraction level you need.

+
+
+
+
  Concept              Type-Erased Wrapper
+  --------------------+------------------------
+  ReadStream     ----->  any_read_stream
+  WriteStream    ----->  any_write_stream
+  Stream         ----->  any_stream
+  ReadSource     ----->  any_read_source
+  WriteSink      ----->  any_write_sink
+  BufferSource   ----->  any_buffer_source  ----> also satisfies any_read_source
+  BufferSink     ----->  any_buffer_sink    ----> also satisfies any_write_sink
+
+
+
+

This is how the Dimovian Ideal is mechanically achieved.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Type-Erased WrapperCapyCobalt

any_read_stream

Yes

any_write_stream

Yes

any_stream

Yes

any_read_source

Yes

any_write_sink

Yes

any_buffer_source

Yes

any_buffer_sink

Yes

+
+
+
+

Mock Streams and Testability

+
+
+

When algorithms operate on type-erased interfaces, testing becomes deterministic. Capy provides mock implementations for every stream concept. Cobalt defines stream abstractions as abstract base classes but does not provide mock implementations for testing. See Write Stream Design for a comparison of the two stream designs.

+
+
+

Capy’s mock types:

+
+
+
    +
  • +

    test::read_stream, test::write_stream — partial I/O mocks

    +
  • +
  • +

    test::stream — connected pair for bidirectional testing

    +
  • +
  • +

    test::read_source, test::write_sink — complete I/O mocks

    +
  • +
  • +

    test::buffer_source, test::buffer_sink — zero-copy mocks

    +
  • +
+
+
+

test::fuse injects errors systematically at every I/O operation point. test::run_blocking executes coroutines synchronously for deterministic unit tests. max_read_size and max_write_size simulate chunked delivery. expect() validates written data.

+
+
+

Tests run without sockets or network access, eliminating non-determinism.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Testing FeatureCapyCobalt

test::read_stream

Yes

test::write_stream

Yes

test::stream (connected pair)

Yes

test::read_source

Yes

test::write_sink

Yes

test::buffer_source

Yes

test::buffer_sink

Yes

Error injection (fuse)

Yes

Synchronous execution (run_blocking)

Yes

Chunked delivery simulation

Yes

Data validation (expect)

Yes

+
+
+
+

Threading Model

+
+
+

Cobalt is single-threaded by design. One executor per thread. Channels are restricted to a single thread — Cobalt’s own documentation states: "Channels can be used to exchange data between different coroutines on a single thread." Primitives cannot be shared between threads.

+
+
+

Capy supports multi-threaded execution. thread_pool distributes work across threads. strand serializes execution without blocking OS threads. The Executor concept is open — implement your own.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ThreadingCapyCobalt

Multi-threaded execution

thread_pool

No

Serialized execution

strand

Single-threaded only

Executor model

Concept-based (open)

Single-threaded (closed)

Cross-thread channels

Yes

No

Primitives shareable across threads

Yes

No

+
+
+
+

Context Propagation

+
+
+

Cobalt stores executor context in thread-local variables. Coroutines access it via this_coro::executor. This works on a single thread with a single executor. This design is scoped to single-threaded, single-executor configurations.

+
+
+

Capy introduces the IoAwaitable protocol and uses it for context propagation. When you co_await, the caller passes its execution environment to the child structurally:

+
+
+
+
auto await_suspend(std::coroutine_handle<> h, io_env const* env);
+
+
+
+

No thread-local state. No ambient context. The executor and stop token flow forward through the call chain via the io_env parameter.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Context PropagationCapyCobalt

Mechanism

await_suspend(h, env)

Thread-local variables

Works with strands

Yes

No

Works with multiple executors

Yes

No

Stop token delivery

Structural (io_env)

this_coro::cancellation_state

+
+
+
+

Cancellation

+
+
+

Both libraries propagate cancellation automatically through coroutine chains. Both support OS-level cancellation of pending I/O operations (CancelIoEx on Windows, IORING_OP_ASYNC_CANCEL on Linux).

+
+
+

Capy uses std::stop_token, propagated via the IoAwaitable protocol’s io_env parameter. The token flows forward structurally alongside the executor.

+
+
+

Cobalt uses Asio’s cancellation_signal and cancellation_slot. Propagation is wired automatically in await_suspend via forward_cancellation. this_coro::cancellation_state provides filtering control over which cancellation types pass through.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CancellationCapyCobalt

Token type

std::stop_token

asio::cancellation_signal

Propagation

Automatic (io_env)

Automatic (slot/signal wiring)

Filtering

Application-level

this_coro::cancellation_state

OS-level cancellation

Yes (via Corosio)

Yes (via Asio)

+
+
+
+

Buffer Sequences

+
+
+

Capy adopts Asio’s buffer sequence model — ConstBufferSequence, MutableBufferSequence — because it works. Capy’s buffer types are fully compatible with Asio’s. You can pass Capy buffers to Asio operations and vice versa, seamlessly. Then Capy extends the model with additional types and algorithms, while still achieving the Dimovian Ideal — none of this requires exposing Asio headers to consumers.

+
+
+

Cobalt does not provide buffer sequence types or dynamic buffer support. Users who need these features use Asio’s types directly, inheriting the DynamicBuffer_v1/DynamicBuffer_v2 split.

+
+
+

Capy has one DynamicBuffer concept. The v1/v2 split in Asio exists because of a fundamental ownership problem: when an async operation takes a buffer by value and completes via callback, who owns the buffer? The original design had flaws, and the fix created two incompatible versions. By going coroutines-only, Capy avoids this entirely. The coroutine frame owns the buffer. Parameters have their lifetimes extended by the suspended frame, and the awaitable lives in the frame alongside them. There is no decay-copy, no ownership transfer, no ambiguity. One concept is sufficient.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Buffer FeatureCapyCobalt

ConstBufferSequence

Yes

Via Asio

MutableBufferSequence

Yes

Via Asio

DynamicBuffer

Unified

None (use Asio directly)

flat_dynamic_buffer

Yes

circular_dynamic_buffer

Yes

buffer_pair

Yes

slice

Yes

front

Yes

consuming_buffers

Yes

buffer_array

Yes

Byte-level trimming

Yes

+
+
+
+

Allocator Control

+
+
+

Cobalt sets up a thread-local PMR resource via main or thread. All coroutines on that thread share it. Every awaitable embeds a fixed SBO buffer:

+
+
+
+
// cobalt/op.hpp
+struct awaitable : awaitable_base
+{
+    char buffer[BOOST_COBALT_SBO_BUFFER_SIZE]; // default: 4096
+    detail::sbo_resource resource{buffer, sizeof(buffer)};
+};
+
+
+
+

If the buffer is exhausted, allocations fall back to the upstream PMR resource or operator new. The buffer size is a compile-time constant. Changing it requires recompiling the library.

+
+
+

Capy leaves these decisions to the user. run_async(executor, allocator)(my_task()) sets the allocator before the task is created. The task’s operator new reads it from thread-local storage. This is a small, flexible customization point that permits usage patterns the authors did not anticipate: per-connection arenas, bounded pools, tracking allocators, per-tenant memory budgets. The allocation strategy is a deployment decision, not a library decision.

+
+
+

recycling_memory_resource provides zero-overhead recycling after warmup. Memory isolated per connection. Reclaimed instantly on disconnect.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Allocator ControlCapyCobalt

Granularity

Per-task

Per-thread

Allocation model

Forward-flow

Thread-local PMR

Per-connection arenas

Yes

No

Recycling allocator

recycling_memory_resource

Custom allocator support

run_async(ex, alloc)

Global setup only

Deterministic freeing

Yes

Non-deterministic on MSVC

+
+
+
+

Execution/Platform Separation

+
+
+

Cobalt is coupled to Asio’s io_context. The execution model and the platform abstractions are one thing.

+
+
+

Capy separates them. The execution model — executors, cancellation, allocation — lives in Capy. Platform abstractions live in Corosio, a companion library that provides native TCP sockets, acceptors, TLS streams, timers, DNS resolution, and signal handling — all built on Capy’s IoAwaitable protocol with native IOCP and epoll backends. You can test Capy’s execution model without a network stack. You can swap the I/O backend without changing your application code.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArchitectureCapyCobalt

Execution model

Capy (independent)

Coupled to io_context

Platform abstractions

Corosio (separate library)

Asio (same dependency)

Testable without I/O backend

Yes

No

Swappable backends

Yes

No

+
+
+
+

Coroutine Overhead

+
+
+

To measure the overhead that coroutines add to a real workload, an experimental JSON serializer drives output through a chain of co_await calls instead of direct function calls. Each JSON value type — null, bool, integer, double, string, array, object — is handled by a coroutine that writes fragments through a write_sink. The baseline is boost::json::serialize, a highly optimized non-coroutine implementation.

+
+
+

The input is numbers.json from the Boost.JSON benchmark suite. Results are best-of-four runs, Clang 20, -O3, Windows x64:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SerializerTimevs baseline

boost::json::serialize

317 us

1.0x

capy::task

537 us

1.69x

cobalt::promise

1,361 us

4.29x

cobalt::task

26,079 us

82.3x

+
+

Capy’s coroutine-driven serializer runs at 1.69x the baseline. Cobalt’s promise is 4.29x. Cobalt’s task is 82x.

+
+
+

The Capy implementation:

+
+
+
+
namespace {
+
+template<class WS> task<> serialize(json::value const& v, WS& ws);
+
+template<class WS> task<> write(std::nullptr_t, WS& ws) {
+    co_await ws.write("null", 4);
+}
+template<class WS> task<> write(bool v, WS& ws) {
+    if(v) co_await ws.write("true", 4);
+    else  co_await ws.write("false", 5);
+}
+template<class WS> task<> write(std::int64_t v, WS& ws) {
+    char buf[32];
+    auto r = std::to_chars(buf, buf + sizeof(buf), v);
+    co_await ws.write(buf, r.ptr - buf);
+}
+template<class WS> task<> write(std::uint64_t v, WS& ws) {
+    char buf[32];
+    auto r = std::to_chars(buf, buf + sizeof(buf), v);
+    co_await ws.write(buf, r.ptr - buf);
+}
+template<class WS> task<> write(double v, WS& ws) {
+    char buf[32];
+    auto r = std::to_chars(buf, buf + sizeof(buf), v);
+    co_await ws.write(buf, r.ptr - buf);
+}
+template<class WS> task<> write(std::string_view v, WS& ws) {
+    co_await ws.write("\"", 1);
+    co_await ws.write(v.data(), v.size());
+    co_await ws.write("\"", 1);
+}
+template<class WS> task<> write(json::array const& v, WS& ws) {
+    co_await ws.write("[", 1);
+    bool first = true;
+    for(auto const& x : v) {
+        if(!first) co_await ws.write(",", 1);
+        first = false;
+        co_await serialize(x, ws);
+    }
+    co_await ws.write("]", 1);
+}
+template<class WS> task<> write(json::object const& v, WS& ws) {
+    co_await ws.write("{", 1);
+    bool first = true;
+    for(auto const& x : v) {
+        if(!first) co_await ws.write(",", 1);
+        first = false;
+        co_await write(x.key(), ws);
+        co_await ws.write(":", 1);
+        co_await serialize(x.value(), ws);
+    }
+    co_await ws.write("}", 1);
+}
+template<class WS> task<> serialize(json::value const& v, WS& ws) {
+    return visit([&](auto const& v) { return write(v, ws); }, v);
+}
+
+struct write_sink {
+    std::string r;
+    task<> write(void const* p, std::size_t n) {
+        r.append(static_cast<char const*>(p), n);
+        co_return;
+    }
+};
+
+} // namespace
+
+std::string serialize_capy_task(json::value const& jv) {
+    write_sink ws;
+    capy::test::run_blocking()(serialize(jv, ws));
+    return std::move(ws.r);
+}
+
+
+
+

Every co_await ws.write(…​) call creates a coroutine frame, suspends, resumes, and destroys. This is the worst case for coroutine overhead — many tiny operations that complete synchronously. In a real application where I/O operations take microseconds or milliseconds, the coroutine machinery becomes negligible.

+
+
+
+
+

Summary

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureCapyCobalt

Design methodology

Use-case-first, coroutines-only

Coroutine layer on hybrid Asio

Implementation hiding

Dimovian Ideal achieved

Backend types exposed

Stream concepts

7 coroutine-only (refinement hierarchy)

Asio’s (hybrid)

Type-erased streams

7 wrappers

None

Mock streams

7 mock types + fuse

None

Threading

Multi-threaded (thread_pool, strand)

Single-threaded

Context propagation

Structural (await_suspend parameters)

Thread-local

Cancellation

std::stop_token, automatic, OS-level

cancellation_signal, automatic, OS-level

Buffer sequences

Extended, unified DynamicBuffer

None (use Asio directly)

Allocator control

Per-task, forward-flow

Per-thread, global setup

Execution/platform

Separated

Coupled

Relink without recompile

Yes

No

+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8n.WhyNotCobaltConcepts.html b/preview/8.design/8n.WhyNotCobaltConcepts.html new file mode 100644 index 0000000..e6df724 --- /dev/null +++ b/preview/8.design/8n.WhyNotCobaltConcepts.html @@ -0,0 +1,1193 @@ + + + + + + + + + + + + + + Write Stream Design: A Side-by-Side Analysis :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Write Stream Design: A Side-by-Side Analysis

+
+
+
+

Both Capy and Cobalt allow you to write a non-template coroutine algorithm that operates on a type-erased write stream. The function signatures look similar:

+
+
+
+
// Capy
+capy::task<> my_algo(capy::any_write_stream& stream);
+
+// Cobalt
+cobalt::task<> my_algo(cobalt::io::write_stream& stream);
+
+
+
+

Both designs solve the same problem. The caller passes a type-erased stream, and the algorithm writes to it without knowing the concrete type. The differences lie in how each library defines the stream abstraction, specifies its contract, propagates context, and manages allocation.

+
+
+

Each section below examines one design choice and its technical consequences.

+
+
+
+
+

Task Requirements

+
+
+

Capy formally defines what makes a task type conforming. Two C++20 concepts form a refinement hierarchy:

+
+
+
+
IoAwaitable
+    |
+    v
+IoRunnable
+
+
+
+

IoAwaitable is the base. It requires a single syntactic property — the await_suspend signature must accept an io_env parameter containing the execution environment:

+
+
+
+
template<typename A>
+concept IoAwaitable =
+    requires(A a, std::coroutine_handle<> h, io_env const* env)
+    {
+        a.await_suspend(h, env);
+    };
+
+
+
+

IoRunnable refines IoAwaitable with operations needed to start a task from non-coroutine contexts: handle(), release(), exception(), and result().

+
+
+
+
template<typename T>
+concept IoRunnable =
+    IoAwaitable<T> &&
+    requires { typename T::promise_type; } &&
+    requires(T& t, T const& ct, typename T::promise_type const& cp)
+    {
+        { ct.handle() } noexcept
+            -> std::same_as<std::coroutine_handle<typename T::promise_type>>;
+        { cp.exception() } noexcept -> std::same_as<std::exception_ptr>;
+        { t.release() } noexcept;
+    } &&
+    (std::is_void_v<decltype(std::declval<T&>().await_resume())> ||
+     requires(typename T::promise_type& p) { p.result(); });
+
+
+
+

Context injection (set_environment, set_continuation) is handled internally by the promise through await_suspend and is not part of any concept.

+
+
+

Each concept has documented syntactic requirements, semantic requirements, conforming signatures, and examples. A user who wants to create a custom task type can read the concept definition and know exactly what to provide. The compiler enforces the syntactic requirements at constraint-check time.

+
+
+

Cobalt’s Approach

+
+

Cobalt uses an associator pattern inherited from Asio. The full documentation for this pattern, from cobalt/doc/design/associators.adoc, reads:

+
+
+
+
+

cobalt uses the associator concept of asio, but simplifies it. That is, it has three associators that are member functions of an awaiting promise.

+
+
+
    +
  • +

    const executor_type & get_executor() (always executor, must return by const ref)

    +
  • +
  • +

    allocator_type get_allocator() (always pmr::polymorphic_allocator<void>)

    +
  • +
  • +

    cancellation_slot_type get_cancellation_slot() (must have the same IF as asio::cancellation_slot)

    +
  • +
+
+
+

cobalt uses concepts to check if those are present in its await_suspend functions.

+
+
+

That way custom coroutines can support cancellation, executors and allocators.

+
+
+

In a custom awaitable you can obtain them like this:

+
+
+
+
+
+
struct my_awaitable
+{
+    bool await_ready();
+    template<typename Promise>
+    void await_suspend(std::coroutine_handle<Promise> h)
+    {
+        if constexpr (requires (Promise p) {p.get_executor();})
+            handle_executor(h.promise().get_executor());
+
+        if constexpr (requires (Promise p) {p.get_cancellation_slot();})
+            if ((cl = h.promise().get_cancellation_slot()).is_connected())
+                cl.emplace<my_cancellation>();
+    }
+
+    void await_resume();
+};
+
+
+
+

The associators are optional member functions on the promise. Each awaitable probes for them independently using if constexpr. This design treats executor, allocator, and cancellation support as independent, opt-in capabilities rather than a single bundled requirement.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

Task requirements

Named concepts (IoAwaitable, IoRunnable)

Implicit associators probed via if constexpr

Specification

Documented syntactic + semantic requirements

Prose description of three member functions

Compiler enforcement

Constraint failure at concept check

Associators are optional; absent ones use defined defaults

Refinement hierarchy

Yes (three levels)

User-authored task types

Implement against documented concept

Follow associator pattern (documented in design guide)

+
+
+
+
+

Context Propagation

+
+
+

The task requirements directly determine how executor and cancellation context reach child operations.

+
+
+

Capy’s IoAwaitable protocol passes the execution environment as an explicit parameter to await_suspend:

+
+
+
+
auto await_suspend(std::coroutine_handle<> h, io_env const* env);
+
+
+
+

The executor and stop token flow forward structurally through the call chain via io_env. If a task’s machinery does not provide them, the code does not compile. There is no fallback.

+
+
+

Cobalt’s approach probes the calling promise. The relevant code from cobalt/detail/task.hpp:

+
+
+
+
template<typename Promise>
+std::coroutine_handle<void> await_suspend(std::coroutine_handle<Promise> h)
+{
+    // ...
+    if constexpr (requires {h.promise().get_cancellation_slot();})
+        if ((cl = h.promise().get_cancellation_slot()).is_connected())
+            cl.emplace<forward_cancellation>(self->promise->signal);
+
+    if constexpr (requires {h.promise().get_executor();})
+        self->promise->exec.emplace(h.promise().get_executor());
+    else
+        self->promise->exec.emplace(this_thread::get_executor());
+    // ...
+}
+
+
+
+

Two things happen when a promise does not provide an associator:

+
+
+
    +
  • +

    If get_executor() is absent, the code falls back to this_thread::get_executor() — a thread-local global. The child task receives the executor most recently set on the current thread.

    +
  • +
  • +

    If get_cancellation_slot() is absent, the cancellation wiring block is skipped. The child task operates without cancellation support.

    +
  • +
+
+
+

Both behaviors are intentional. Cobalt treats associators as optional capabilities — a task without get_cancellation_slot() simply does not propagate cancellation to its children. This is a design choice that favors flexibility: tasks can participate in the system without implementing every associator. The trade-off is that omitting an associator produces no compile-time diagnostic, so the behavior difference must be understood by the author of the custom task.

+
+
+

In Capy, the equivalent of "no cancellation" is passing std::stop_token{} (a never-stop token) explicitly. Both designs support uncancellable operations; they differ in whether that choice is expressed through presence of a parameter or absence of a member function.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

Mechanism

Explicit await_suspend(h, env) parameter

Promise probing via if constexpr

Missing executor

Compile error

Falls back to this_thread::get_executor()

Missing cancellation

Compile error (pass std::stop_token{} to opt out)

Skipped by design (child uses no cancellation)

Diagnostic on omission

Yes (constraint failure)

No (optional by design)

+
+
+
+

Buffer Sequences

+
+
+

Cobalt’s write_stream accepts buffers through a concrete type:

+
+
+
+
struct write_stream
+{
+    virtual ~write_stream() = default;
+    virtual write_op write_some(const_buffer_sequence buffer) = 0;
+};
+
+
+
+

const_buffer_sequence is a fixed type that accepts either a single asio::const_buffer or a std::span<const asio::const_buffer>:

+
+
+
+
struct const_buffer_sequence
+{
+    const_buffer_sequence(asio::const_buffer head);
+    const_buffer_sequence(asio::mutable_buffer head);
+
+    template<typename T>
+        requires (std::constructible_from<
+            std::span<const asio::const_buffer>, const T&>)
+    const_buffer_sequence(const T& value);
+
+    const_buffer_sequence(std::span<const asio::const_buffer> spn);
+    // ...
+};
+
+
+
+

This is a subset of Asio’s full ConstBufferSequence concept. Buffer sequence types that do not convert to const_buffer or span<const asio::const_buffer> cannot be passed through this interface.

+
+
+

Capy’s WriteStream concept requires write_some to accept any ConstBufferSequence:

+
+
+
+
template<typename T>
+concept WriteStream =
+    requires(T& stream, const_buffer_archetype buffers)
+    {
+        { stream.write_some(buffers) } -> IoAwaitable;
+        // ...
+    };
+
+
+
+

The type-erased wrapper any_write_stream also models the WriteStream concept. Its write_some is a template that accepts any ConstBufferSequence:

+
+
+
+
template<ConstBufferSequence CB>
+auto
+any_write_stream::write_some(CB buffers);
+
+
+
+

Both the concept and the wrapper accept full buffer sequences. Type erasure does not narrow the interface.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

write_some parameter

template<ConstBufferSequence CB>

const_buffer_sequence (concrete type)

Accepted buffer types

Any ConstBufferSequence

const_buffer, span<const const_buffer>

Type-erased wrapper accepts full concept

Yes

Custom buffer sequence types

Accepted

Must convert to supported representations

+
+
+
+

Semantic Specification

+
+
+

Cobalt’s entire documentation for write_stream, from cobalt/doc/reference/io/stream.adoc, is:

+
+
+
+
+

A stream is an io object that allows reads and writes, such as a tcp socket.

+
+
+
+
+

Followed by the struct definition:

+
+
+
+
struct write_stream
+{
+    virtual ~write_stream() = default;
+    virtual write_op write_some(const_buffer_sequence buffer) = 0;
+};
+
+
+
+

The documentation describes what a stream is but does not specify behavioral details for write_some: empty buffer handling, error reporting conventions, partial write guarantees, buffer consumption order, or buffer lifetime assumptions. These details are left to the implementor’s judgment or inferred from Asio conventions.

+
+
+

Capy’s WriteStream concept includes semantic requirements in the concept’s documentation:

+
+
+
+
// From capy/concept/write_stream.hpp
+
+// Semantic Requirements:
+//
+// If buffer_size( buffers ) > 0, the operation writes one or more
+// bytes of data to the stream from the buffer sequence:
+//
+//   On success: !ec, and n is the number of bytes written.
+//   On error: ec, and n is 0.
+//
+// If buffer_empty( buffers ) is true, the operation completes
+// immediately. !ec, and n is 0.
+//
+// Buffers in the sequence are written completely before proceeding
+// to the next buffer.
+//
+// Buffer Lifetime:
+//
+// The caller must ensure that the memory referenced by buffers
+// remains valid until the co_await expression returns.
+
+
+
+

The concept also includes a coroutine-specific warning about buffer lifetime:

+
+
+
+
// Warning: 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.
+
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SpecificationCapyCobalt

Empty buffer behavior

Documented (immediate completion, no error)

Error reporting semantics

Documented (ec + n == 0)

Partial write guarantees

Documented (buffers consumed in order)

Buffer lifetime requirements

Documented

Coroutine buffer lifetime warning

Yes

Conforming signature examples

Yes

+
+
+
+

Operation Implementation

+
+
+

Cobalt’s write_stream::write_some returns write_op, a concrete operation type. The write_op struct from cobalt/io/ops.hpp:

+
+
+
+
struct write_op final : op<system::error_code, std::size_t>
+{
+    const_buffer_sequence buffer;
+
+    using     implementation_t =
+        void(void*, const_buffer_sequence,
+             completion_handler<system::error_code, std::size_t>);
+    using try_implementation_t =
+        void(void*, const_buffer_sequence,
+             handler<system::error_code, std::size_t>);
+
+    write_op(const_buffer_sequence buffer,
+             void* this_,
+             implementation_t* implementation,
+             try_implementation_t* try_implementation = nullptr);
+
+    void initiate(
+        completion_handler<system::error_code, std::size_t> handler) final;
+    void ready(
+        handler<system::error_code, std::size_t> handler) final;
+};
+
+
+
+

Implementing write_stream requires constructing a write_op with two function pointers and a void*. The full documentation for these function pointers, from cobalt/doc/reference/io/ops.adoc, is:

+
+
+
+
+

Most functionality in this wrapper is implemented with operations.

+
+
+

They are type-erase, but not by using virtual. This makes devirtualization easier. The implementation function must be provided, where as try_implementation_t is optional and will be used in the ready function. Both will be called with void *this as the first parameter.

+
+
+
+
+

The documentation describes the mechanical role of each function pointer but does not specify what the implementation function must do with the buffer, what completion semantics to follow, how to report errors through the completion_handler, or under what conditions try_implementation should complete synchronously. Implementors can look to the existing I/O wrappers (e.g., stream_socket) as reference implementations.

+
+
+

In Capy, the implementation contract lives in the WriteStream concept definition. A type satisfies WriteStream by providing a write_some member function template that returns an IoAwaitable decomposing to (error_code, std::size_t). The semantic requirements are part of the concept. There is no separate operation type to construct and no function pointers to provide.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

How to implement

Satisfy the WriteStream concept

Construct write_op with function pointers + void*

Contract location

Concept definition (javadoc)

Prose paragraph in ops reference

Implementation function semantics

Specified (in concept)

Inferred from existing wrappers

Intermediate types required

None (concept is the contract)

write_op, completion_handler, handler

+
+
+
+

Awaitable Allocation

+
+
+

Every co_await on a write_op in Cobalt allocates a fixed-size buffer in the coroutine frame. The chain is:

+
+
+
    +
  1. +

    write_stream::write_some returns write_op

    +
  2. +
  3. +

    write_op final : op<system::error_code, std::size_t>

    +
  4. +
  5. +

    op<>::operator co_await() returns op<>::awaitable

    +
  6. +
  7. +

    op<>::awaitable contains a 4096-byte SBO buffer:

    +
  8. +
+
+
+
+
// cobalt/op.hpp
+struct awaitable : awaitable_base
+{
+    char buffer[BOOST_COBALT_SBO_BUFFER_SIZE]; // default: 4096
+    detail::sbo_resource resource{buffer, sizeof(buffer)};
+
+    awaitable(op<Args...>* op_) : awaitable_base(op_, &resource) {}
+    // ...
+};
+
+
+
+

write_op is final. The return type of write_stream::write_some is fixed. Subclasses of write_stream cannot change the return type, the allocation strategy, or the SBO buffer size. Every co_await stream.write_some(buf) places this 4096-byte awaitable in the coroutine frame regardless of whether the underlying implementation needs it.

+
+
+

Capy’s any_write_stream takes a different approach. The constructor preallocates storage sized exactly to the wrapped stream’s awaitable type:

+
+
+
+
// capy/io/any_write_stream.hpp
+template<WriteStream S>
+    requires (!std::same_as<std::decay_t<S>, any_write_stream>)
+any_write_stream::any_write_stream(S s)
+    : vt_(&vtable_for_impl<S>::value)
+{
+    // ...
+    storage_ = ::operator new(sizeof(S));
+    stream_ = ::new(storage_) S(std::move(s));
+
+    // Preallocate the awaitable storage
+    cached_awaitable_ = ::operator new(vt_->awaitable_size);
+    // ...
+}
+
+
+
+

After construction, each co_await stream.write_some(buf) reuses this preallocated storage. There is no per-operation allocation and no fixed-size buffer in the coroutine frame.

+
+
+

If users prefer a different allocation strategy, they can write algorithms directly against the WriteStream concept and build their own wrapper. The concept and the type-erased wrapper are separate layers. Cobalt’s abstract base class fuses the abstraction and the allocation strategy into one type.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

Per-operation allocation

None (preallocated at construction)

4096-byte SBO buffer per co_await

Storage sizing

Exact (sized to wrapped type)

Fixed (BOOST_COBALT_SBO_BUFFER_SIZE)

Configurable by subclass

N/A (concept + wrapper are separate)

No (write_op is final)

Custom allocation strategy

Write against WriteStream concept

Not possible (return type is fixed)

+
+
+
+

Concept vs. Abstract Base Class

+
+
+

The preceding sections each examined a specific design choice. A common thread runs through them.

+
+
+

Cobalt’s write_stream is an abstract base class. The abstraction and the runtime wrapper are the same type. Writing against the abstraction means using virtual dispatch. The return type (write_op), the buffer parameter type (const_buffer_sequence), the allocation strategy (4096-byte SBO), and the context propagation mechanism (promise probing) are all fixed by the base class definition.

+
+
+

Capy separates the abstraction from the wrapper. WriteStream is a C++20 concept:

+
+
+
+
template<typename T>
+concept WriteStream =
+    requires(T& stream, const_buffer_archetype buffers)
+    {
+        { stream.write_some(buffers) } -> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(stream.write_some(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+

any_write_stream is a type-erased wrapper that satisfies this concept. It is one possible reification, not the only one. Users can:

+
+
+
    +
  • +

    Write generic algorithms constrained by WriteStream — these work with any conforming stream, with no virtual dispatch overhead.

    +
  • +
  • +

    Use any_write_stream when runtime polymorphism is needed — it provides type erasure with preallocated awaitable storage.

    +
  • +
  • +

    Build a custom wrapper with a different allocation or dispatch strategy — the concept defines the contract independently of any particular wrapper.

    +
  • +
+
+
+

This separation is the architectural root of the differences examined in this document. It is what enables full buffer sequence support at the type-erased layer, formal semantic specification in a concept definition, user-selectable allocation strategies, and explicit context propagation through await_suspend parameters.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyCobalt

Abstraction mechanism

C++20 concept (WriteStream)

Abstract base class (write_stream)

Runtime wrapper

Separate (any_write_stream)

Same type as abstraction

Generic algorithms (no type erasure)

Yes (constrain on concept)

No (must use virtual dispatch)

Custom wrappers

Yes (concept is independent)

No (locked to write_op return type)

+
+
+
+

Summary

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Design ChoiceCapyCobalt

Task requirements

Named concept hierarchy (IoAwaitableIoRunnable)

Implicit associators (get_executor, get_cancellation_slot, get_allocator)

Context propagation

Explicit await_suspend parameters

Promise probing via if constexpr with thread-local fallback

Buffer sequence support

Full ConstBufferSequence (concept + wrapper)

const_buffer_sequence (concrete subset)

Semantic specification

Documented in concept (empty buffers, errors, ordering, lifetime)

Struct definition; semantics follow Asio conventions

Operation implementation

Satisfy concept; wrapper handles the rest

Construct write_op with function pointers + void*

Awaitable allocation

Preallocated at construction (exact size)

4096-byte SBO per co_await (fixed, final)

Abstraction mechanism

Concept (compile-time) + wrapper (runtime), separable

Abstract base class (fused)

+
+
+ + +
+
+ +
+ + diff --git a/preview/8.design/8o.WhyNotTMC.html b/preview/8.design/8o.WhyNotTMC.html new file mode 100644 index 0000000..5da743f --- /dev/null +++ b/preview/8.design/8o.WhyNotTMC.html @@ -0,0 +1,1330 @@ + + + + + + + + + + + + + + Capy and TooManyCooks: A Comparison :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Capy and TooManyCooks: A Comparison

+
+
+
+

You want to write async code in C++. You’ve heard about coroutines. Two libraries exist: Capy and TooManyCooks (TMC). Both let you write co_await. Both run on multiple threads.

+
+
+

One was designed for network I/O. The other was designed for compute tasks. Choosing the wrong one creates friction. This document helps you choose.

+
+
+
+
+

The Simple Version

+
+
+

Capy:

+
+
+
    +
  • +

    Built for waiting on things (network, files, timers)

    +
  • +
  • +

    When data arrives, your code wakes up in the right place automatically

    +
  • +
  • +

    Cancellation works - if you stop waiting, pending operations stop too

    +
  • +
  • +

    Handles data buffers natively - the bytes flowing through your program

    +
  • +
+
+
+

TMC:

+
+
+
    +
  • +

    Built for doing things (calculations, parallel work)

    +
  • +
  • +

    Multi-threaded work pool that keeps CPUs busy

    +
  • +
  • +

    Priority levels so important work runs first (16 of them, to be precise)

    +
  • +
  • +

    Mid-coroutine executor switching for flexible work migration

    +
  • +
  • +

    No built-in I/O - you add that separately (via Asio integration)

    +
  • +
+
+
+

If you’re building a network server, one of these is swimming upstream.

+
+
+ + + + + +
+ + +On priorities: Capy defines executors using a concept. Nothing stops you from implementing a priority-enforcing executor. You could have 24 priority levels, if 16 somehow felt insufficient. +
+
+
+
+
+

Where Does Your Code Run?

+
+
+

When async code finishes waiting, it needs to resume somewhere. Where?

+
+
+

Capy’s answer: The same place it started. Automatically.

+
+
+
    +
  • +

    Context flows forward through await_suspend(h, env) where env is an io_env

    +
  • +
  • +

    Your coroutine started on executor X? It resumes on executor X.

    +
  • +
  • +

    Child tasks can run on different executors via run(other_ex)(child_task())

    +
  • +
+
+
+

TMC’s answer: Where you tell it, with flexibility to change mid-execution.

+
+
+
    +
  • +

    Context flows via tmc::detail::awaitable_traits - a traits-based injection mechanism

    +
  • +
  • +

    Thread-local variables track the current executor for quick access

    +
  • +
  • +

    Coroutines can hop executors mid-body via resume_on() and enter()/exit()

    +
  • +
  • +

    Works fine within TMC’s ecosystem; integrating external I/O requires the coordination headers (ex_asio.hpp, aw_asio.hpp)

    +
  • +
+
+
+

Both libraries propagate executor context. They differ in mechanism and mobility.

+
+
+
+
+

Executor Mobility

+
+
+

TMC allows a coroutine to switch executors mid-body:

+
+
+
+
tmc::task<void> example() {
+    // Running on executor A
+    co_await tmc::resume_on(executor_b);
+    // Now running on executor B - same coroutine!
+
+    // Or scoped:
+    auto scope = co_await tmc::enter(io_exec);
+    // Temporarily on io_exec
+    co_await scope.exit();
+    // Back to original
+}
+
+
+
+

This is powerful for compute workloads where work can migrate between thread pools.

+
+
+

Capy’s design choice: Intentionally prevent mid-coroutine executor switching. A coroutine stays on its bound executor for its entire lifetime. Child tasks can run on different executors via run(other_ex)(child_task()), but the parent never moves.

+
+
+

Why Capy prevents this: I/O objects often have invariants tied to their executor:

+
+
+
    +
  • +

    A socket may only be accessed from threads associated with a specific io_context

    +
  • +
  • +

    File handles on Windows IOCP must complete on the same context they were initiated

    +
  • +
  • +

    Timer state is executor-specific

    +
  • +
+
+
+

Allowing a coroutine holding I/O objects to hop executors mid-body would break these invariants. TMC doesn’t face this constraint because it’s a compute scheduler - work items don’t carry I/O state with executor affinity.

+
+
+
+
+

Stopping Things

+
+
+

What happens when you need to cancel an operation?

+
+
+

Capy: Stop tokens propagate automatically through the call chain.

+
+
+
    +
  • +

    Cancel at the top, everything below receives the signal

    +
  • +
  • +

    Pending I/O operations cancel at the OS level (CancelIoEx, IORING_OP_ASYNC_CANCEL)

    +
  • +
  • +

    Clean shutdown, no leaked resources

    +
  • +
+
+
+

TMC: You manage cancellation yourself.

+
+
+
    +
  • +

    Stop tokens exist in C++20 but TMC doesn’t propagate them automatically

    +
  • +
  • +

    This is intentional: TMC is designed to work with various external libraries

    +
  • +
  • +

    Pending work completes, or you wait for it

    +
  • +
+
+
+

The TMC author acknowledged that automatic cancellation propagation is an "excellent killer feature" for an integrated I/O stack like Capy.

+
+
+
+
+

Keeping Things Orderly

+
+
+

Both libraries support multi-threaded execution. Sometimes you need guarantees: "these operations must not overlap."

+
+
+

Capy’s strand:

+
+
+
    +
  • +

    Wraps any executor

    +
  • +
  • +

    Coroutines dispatched through a strand never run concurrently

    +
  • +
  • +

    Even if one suspends (waits for I/O), ordering is preserved

    +
  • +
  • +

    When you resume, the world is as you left it

    +
  • +
+
+
+

TMC’s ex_braid:

+
+
+
    +
  • +

    Also serializes execution

    +
  • +
  • +

    But: when a coroutine suspends, the lock is released

    +
  • +
  • +

    Another coroutine may enter and begin executing

    +
  • +
  • +

    When you resume, the state may have changed

    +
  • +
+
+
+

TMC’s documentation describes this as "optimized for higher throughput with many serialized tasks." This is a design choice. Whether it matches your mental model is a separate question.

+
+
+ + + + + +
+ + +Neither library prevents the caller from initiating multiple concurrent I/O operations on the same object - that’s always the caller’s responsibility. Both provide mutual exclusion for coroutine/handler execution only, not I/O operation queuing. +
+
+
+
+
+

Working with Data

+
+
+

Network code moves bytes around. A lot of bytes. Efficiently.

+
+
+

Capy provides:

+
+
+
    +
  • +

    Buffer sequences (scatter/gather I/O without copying)

    +
  • +
  • +

    Algorithms: slice, copy, concatenate, consume

    +
  • +
  • +

    Dynamic buffers that grow as needed

    +
  • +
  • +

    Type-erased streams: write code once, use with any stream type

    +
  • +
+
+
+

TMC provides:

+
+
+
    +
  • +

    Nothing. TMC is not an I/O library.

    +
  • +
  • +

    You use Asio’s buffers through the integration layer.

    +
  • +
+
+
+
+
+

Memory Allocation Control

+
+
+

HALO (Heap Allocation Lowering Optimization) lets compilers eliminate coroutine frame allocations when the frame’s lifetime doesn’t escape the caller. But I/O operations always escape - the awaitable must live until the kernel/reactor completes the operation.

+
+
+

Capy provides:

+
+
+
    +
  • +

    Custom allocator propagation via run_async(ex, allocator) and run(allocator)

    +
  • +
  • +

    Per-connection arena allocation

    +
  • +
  • +

    Memory isolation between connections

    +
  • +
  • +

    Instant reclamation on connection close

    +
  • +
+
+
+
+
std::pmr::monotonic_buffer_resource arena;
+run_async(ex, &arena)(handle_connection(socket));
+// On disconnect: entire arena reclaimed instantly
+
+
+
+

TMC provides:

+
+
+
    +
  • +

    Global ::operator new (with cache-line padding)

    +
  • +
  • +

    Recommends tcmalloc for improved performance

    +
  • +
  • +

    No per-operation allocator control

    +
  • +
+
+
+

For I/O workloads where HALO cannot apply, allocator control is essential, not optional.

+
+
+
+
+

Getting Technical: The IoAwaitable Protocol

+
+
+

When you write co_await something, what happens?

+
+
+

Standard C++20:

+
+
+
+
void await_suspend(std::coroutine_handle<> h);
+// or
+bool await_suspend(std::coroutine_handle<> h);
+// or
+std::coroutine_handle<> await_suspend(std::coroutine_handle<> h);
+
+
+
+

The awaitable receives a handle to resume. That’s all. No information about where to resume, no cancellation mechanism.

+
+
+

Capy extends this:

+
+
+
+
auto await_suspend(std::coroutine_handle<> h, io_env const* env);
+
+
+
+

The awaitable receives:

+
+
+
    +
  • +

    h — The handle (for resumption)

    +
  • +
  • +

    env — The execution environment containing:

    +
    +
      +
    • +

      env→executor — The executor (where to resume)

      +
    • +
    • +

      env→stop_token — A stop token (for cancellation)

      +
    • +
    • +

      env→allocator — An optional allocator for frame allocation

      +
    • +
    +
    +
  • +
+
+
+

TMC’s approach:

+
+
+

Standard signature, plus traits-based context injection:

+
+
+
+
// TMC propagates context via awaitable_traits<T>
+awaitable_traits<T>::set_continuation(awaitable, continuation);
+awaitable_traits<T>::set_continuation_executor(awaitable, executor);
+
+
+
+

TMC also tracks this_thread::executor and this_task.prio in thread-local variables for quick access.

+
+
+

Both approaches achieve context propagation. Neither is compatible with arbitrary third-party awaitables without explicit support.

+
+
+
+
+

Protocol Strictness

+
+
+

What happens when you co_await an awaitable that doesn’t implement the extended protocol?

+
+
+

Capy: Compile-time error.

+
+
+
+
// From task.hpp transform_awaitable()
+else
+{
+    static_assert(sizeof(A) == 0, "requires IoAwaitable");
+}
+
+
+
+

TMC: Wrap in a trampoline that captures current context.

+
+
+
+
// From task.hpp await_transform()
+return tmc::detail::safe_wrap(std::forward<Awaitable>(awaitable));
+
+
+
+

Trade-offs:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyTMC

Unknown awaitables

Compilation failure

safe_wrap() trampoline

Context propagation

Required by protocol

Lost for wrapped awaitables

Integration flexibility

Requires protocol adoption

More permissive interop

+
+

Capy makes the conscious decision that silent degradation is worse than compilation failure. If an awaitable doesn’t carry context forward, the code doesn’t compile. This prevents subtle bugs where cancellation or executor affinity silently stops working.

+
+
+

TMC’s approach is more flexible for incremental adoption but risks silent context loss when mixing TMC with non-TMC awaitables.

+
+
+
+
+

Integration Approaches

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
AspectTMCCapy

External adapter

Traits specialization (non-intrusive)

Member function (intrusive)

Unknown awaitables

safe_wrap() trampoline

static_assert failure

Context mechanism

Traits + TLS capture

Parameter passing

+
+

Both require explicit support from awaitables. TMC’s traits are external specializations, making it theoretically easier to build adapters for third-party libraries without modifying them. Capy’s member function signature requires the awaitable itself to implement the protocol.

+
+
+

Practically, both require cooperation from awaitable authors for full functionality.

+
+
+
+
+

I/O Performance: Native vs Integration

+
+
+

TMC integrates with Asio via aw_asio.hpp/ex_asio.hpp. Corosio provides native I/O objects built on Capy’s protocol.

+
+
+

TMC + Asio call chain for socket.async_read_some(buf, tmc::aw_asio):

+
+
+
    +
  1. +

    async_result<aw_asio_t>::initiate() - creates awaitable, stores initiation + args in std::tuple

    +
  2. +
  3. +

    operator co_await() returns aw_asio_impl

    +
  4. +
  5. +

    await_suspend() calls async_initiate()initiate_await(callback) - virtual call

    +
  6. +
  7. +

    std::apply unpacks tuple, invokes Asio initiation

    +
  8. +
  9. +

    Asio type-erases handler into internal storage

    +
  10. +
  11. +

    On completion: callback stores result, calls resume_continuation()

    +
  12. +
  13. +

    resume_continuation() checks executor/priority, posts if different

    +
  14. +
+
+
+

Corosio native call chain for socket.read_some(buf):

+
+
+
    +
  1. +

    Returns read_some_awaitable (stack object)

    +
  2. +
  3. +

    await_suspend(h, ex, token) calls impl_.read_some() - virtual call to platform impl

    +
  4. +
  5. +

    Platform impl issues direct syscall (recv/WSARecv)

    +
  6. +
  7. +

    Registers with reactor

    +
  8. +
  9. +

    On completion: ex.dispatch(h) - inline resume when on io_context executor

    +
  10. +
+
+
+

Overhead comparison:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectTMC + AsioCorosio Native

Virtual calls

1 (initiate_await)

1 (platform impl)

Type erasure

Asio handler + ex_any

executor_ref only

Tuple packing

Yes (init args)

No

Handler storage

Asio internal (likely heap)

Operation slot in socket

Completion dispatch

Checks executor/priority, posts if different

dispatch() call, inline resume on io_context

Lambda wrapper

Yes (ex_asio::post)

No

+
+

The critical path difference is completion. TMC+Asio goes through resume_continuation() which checks executor/priority and often posts via asio::post(). Corosio’s dispatch() can resume the coroutine inline when already on the io_context executor, avoiding the post overhead.

+
+
+
+
+

Type Erasure

+
+
+

Capy:

+
+
+
    +
  • +

    any_stream, any_read_stream, any_write_stream

    +
  • +
  • +

    Write a function taking any_stream& - it compiles once

    +
  • +
  • +

    One virtual call per I/O operation

    +
  • +
  • +

    Clean ABI boundaries

    +
  • +
+
+
+

TMC:

+
+
+
    +
  • +

    Traits-based: executor_traits<T> specializations

    +
  • +
  • +

    Type-erased executor: ex_any (function pointers, not virtuals)

    +
  • +
  • +

    No stream abstractions (not an I/O library)

    +
  • +
+
+
+
+
+

Different Positions in the Tree of Need

+
+
+

TMC and Capy occupy different architectural positions. Rather than competing, they serve different needs:

+
+
+

TMC sits above I/O:

+
+
+
    +
  • +

    Compute scheduler designed for CPU-bound parallel work

    +
  • +
  • +

    Integrates with existing I/O solutions (Asio)

    +
  • +
  • +

    Flexible executor mobility for work migration

    +
  • +
  • +

    Permissive interop via safe_wrap() for gradual adoption

    +
  • +
+
+
+

Capy sits below compute:

+
+
+
    +
  • +

    I/O foundation designed for network/file operations

    +
  • +
  • +

    Strict protocol enforcement prevents silent failures

    +
  • +
  • +

    Executor stability protects I/O object invariants

    +
  • +
  • +

    Allocator control where HALO cannot apply

    +
  • +
+
+
+

Neither is "more fundamental." If you’re building a network server, Capy’s constraints exist to protect you. If you’re parallelizing CPU work, TMC’s flexibility is valuable.

+
+
+
+
+

Corosio: Proof It Works

+
+
+

Capy is a foundation. Corosio builds real networking on it:

+
+
+
    +
  • +

    TCP sockets, acceptors

    +
  • +
  • +

    TLS streams (WolfSSL)

    +
  • +
  • +

    Timers, DNS resolution, signal handling

    +
  • +
  • +

    Native backends: IOCP (Windows), epoll (Linux), io_uring (planned)

    +
  • +
+
+
+

All built on Capy’s IoAwaitable protocol. Coroutines only. No callbacks.

+
+
+
+
+

When to Use Each

+
+
+

Choose TMC if:

+
+
+
    +
  • +

    CPU-bound parallel algorithms

    +
  • +
  • +

    Compute workloads needing work-stealing or priority scheduling (1-16 levels)

    +
  • +
  • +

    Work that benefits from mid-coroutine executor migration

    +
  • +
  • +

    You’re already using Asio and want a scheduler on top

    +
  • +
  • +

    Gradual adoption with mixed awaitable sources

    +
  • +
+
+
+

Choose Capy if:

+
+
+
    +
  • +

    Network servers or clients

    +
  • +
  • +

    Protocol implementations

    +
  • +
  • +

    I/O-bound workloads

    +
  • +
  • +

    You want cancellation that propagates automatically

    +
  • +
  • +

    You want buffers and streams as first-class concepts

    +
  • +
  • +

    You need per-connection allocator control

    +
  • +
  • +

    You prefer strict compile-time protocol enforcement

    +
  • +
+
+
+

Or use both:

+
+
+

TMC for compute scheduling, Capy/Corosio for I/O. They can coexist at different layers of your application.

+
+
+
+
+

Summary

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AspectCapyTooManyCooks

Primary purpose

I/O foundation

Compute scheduling

Threading

Multi-threaded (thread_pool)

Multi-threaded (work-stealing)

Executor mobility

Fixed per coroutine

Mid-body switching (resume_on)

Serialization

strand (ordering preserved across suspend)

ex_braid (lock released on suspend)

Context propagation

await_suspend(h, env)

awaitable_traits + TLS

Unknown awaitables

static_assert failure

safe_wrap() trampoline

Cancellation

Automatic propagation

Manual

Allocator control

Per-task (std::pmr)

Global (::operator new)

Buffer sequences

Yes

No (use Asio)

Stream concepts

Yes (ReadStream, WriteStream, etc.)

No

Type-erased streams

Yes (any_stream)

No

I/O support

Via Corosio (native IOCP/epoll/io_uring)

Via Asio integration headers

Priority scheduling

Implement your own

Built-in (1-16 levels)

Work-stealing

No

Yes

Executor model

Concept-based (user-extensible)

Traits-based (executor_traits<T>)

+
+
+
+

Revision History

+
+ ++++ + + + + + + + + + + + + +
DateChanges

2026-02-04

Revised to correct inaccuracies regarding TMC’s context propagation mechanism. The author of TooManyCooks provided feedback clarifying that TMC implements executor affinity via tmc::detail::awaitable_traits, not just thread-local state. Reframed comparison to acknowledge both libraries as complementary solutions for different architectural positions rather than competitors.

+
+
+ + +
+
+ +
+ + diff --git a/preview/_/css/boostlook.css b/preview/_/css/boostlook.css new file mode 120000 index 0000000..ba7e560 --- /dev/null +++ b/preview/_/css/boostlook.css @@ -0,0 +1 @@ +../../../boostlook-v3.css \ No newline at end of file diff --git a/preview/_/css/site.css b/preview/_/css/site.css new file mode 100644 index 0000000..2455b43 --- /dev/null +++ b/preview/_/css/site.css @@ -0,0 +1,3 @@ +@import "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200";@import "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css";@font-face{font-family:Roboto;font-style:normal;font-weight:400;src:url(../font/roboto-latin-400-normal.woff2) format("woff2"),url(../font/roboto-latin-400-normal.woff) format("woff");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}@font-face{font-family:Roboto;font-style:italic;font-weight:400;src:url(../font/roboto-latin-400-italic.woff2) format("woff2"),url(../font/roboto-latin-400-italic.woff) format("woff");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}@font-face{font-family:Roboto;font-style:normal;font-weight:500;src:url(../font/roboto-latin-500-normal.woff2) format("woff2"),url(../font/roboto-latin-500-normal.woff) format("woff");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}@font-face{font-family:Roboto;font-style:italic;font-weight:500;src:url(../font/roboto-latin-500-italic.woff2) format("woff2"),url(../font/roboto-latin-500-italic.woff) format("woff");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}@font-face{font-family:Roboto Mono;font-style:normal;font-weight:400;src:url(../font/roboto-mono-latin-400-normal.woff2) format("woff2"),url(../font/roboto-mono-latin-400-normal.woff) format("woff");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}@font-face{font-family:Roboto Mono;font-style:normal;font-weight:500;src:url(../font/roboto-mono-latin-500-normal.woff2) format("woff2"),url(../font/roboto-mono-latin-500-normal.woff) format("woff");unicode-range:U+00??,U+0131,U+0152-0153,U+02bb-02bc,U+02c6,U+02da,U+02dc,U+2000-206f,U+2074,U+20ac,U+2122,U+2191,U+2193,U+2212,U+2215,U+feff,U+fffd}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}html{-webkit-box-sizing:border-box;box-sizing:border-box;font-size:.83333rem;height:100%;scroll-behavior:smooth}@media screen and (min-width:1024px){html{font-size:1rem}}body{background:#fff;color:#314a57;font-family:Noto Sans,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:var(--body-line-height);font-size:inherit;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere}a{text-decoration:none}a:hover{text-decoration:underline}a:active{background-color:none}code,kbd,pre{font-family:Noto Mono,SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}b,dt,strong,th{font-weight:600}em em{font-style:normal}strong strong{font-weight:400}button{cursor:pointer;font-family:inherit;font-size:1em;line-height:var(--body-line-height);margin:0}button::-moz-focus-inner{border:none;padding:0}summary{cursor:pointer;-webkit-tap-highlight-color:transparent;outline:none}table{word-wrap:normal}object[type="image/svg+xml"]:not([width]){width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}::-webkit-input-placeholder{opacity:.5}::-moz-placeholder{opacity:.5}:-ms-input-placeholder{opacity:.5}::-ms-input-placeholder{opacity:.5}::placeholder{opacity:.5}@media (pointer:fine){@supports (scrollbar-width:thin){html{scrollbar-color:#c1c1c1 #eaf0f3}body *{scrollbar-width:thin;scrollbar-color:#c1c1c1 transparent}}html::-webkit-scrollbar{background-color:#eaf0f3;height:12px;width:12px}body ::-webkit-scrollbar{height:6px;width:6px}::-webkit-scrollbar-thumb{background-clip:padding-box;background-color:#c1c1c1;border:3px solid transparent;border-radius:12px}body ::-webkit-scrollbar-thumb{border-width:1.75px;border-radius:6px}::-webkit-scrollbar-thumb:hover{background-color:#9c9c9c}}@media screen and (min-width:1024px){.body{display:-webkit-box;display:-ms-flexbox;display:flex}}.nav-container{position:fixed;top:var(--navbar-height);left:0;width:100%;font-size:1.0625rem;z-index:1;visibility:hidden}@media screen and (min-width:769px){.nav-container{width:16.875rem}}@media screen and (min-width:1024px){.nav-container{font-size:.96875rem;-webkit-box-flex:0;-ms-flex:none;flex:none;position:static;top:0;visibility:visible}}.nav-container.is-active{visibility:visible}.nav{position:relative;top:2.8125rem;height:calc(100vh - var(--navbar-height) - 2.8125rem)}@media screen and (min-width:769px){.nav{-webkit-box-shadow:.5px 0 3px #c1c1c1;box-shadow:.5px 0 3px #c1c1c1}}@media screen and (min-width:1024px){.nav{top:var(--navbar-height);-webkit-box-shadow:none;box-shadow:none;position:sticky;height:calc(100vh - var(--navbar-height))}}.nav a{color:inherit}.nav .panels{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:inherit}html.is-clipped--nav{overflow-y:hidden}.nav-panel-menu{overflow-y:scroll;-ms-scroll-chaining:none;overscroll-behavior:none;height:calc(100% - 2.8125rem)}.nav-panel-menu:not(.is-active) .nav-menu{opacity:.75}.nav-panel-menu:not(.is-active)::after{content:"";background:rgba(0,0,0,.5);display:block;position:absolute;top:0;right:0;bottom:0;left:0}.nav-menu{min-height:100%;line-height:1.35;position:relative}.nav-menu .title-row{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;gap:.5rem}.nav-menu h3.title{color:#424242;font-size:inherit;font-weight:600;margin:0;padding:.25em 0 .125em}.nav-list{list-style:none;margin:0 0 0 .75rem;padding:0}.nav-menu>.nav-list+.nav-list{margin-top:.5rem}.nav-item{margin-top:.5em}.nav-item-toggle~.nav-list{padding-bottom:.125rem}.nav-item[data-depth="0"]>.nav-list:first-child{display:block;margin:0}.nav-item:not(.is-active)>.nav-list{display:none}.nav-item-toggle{background:transparent url(../img/caret.svg) no-repeat 50%/50%;border:none;outline:none;line-height:inherit;padding:0;position:absolute;height:1.35em;width:1.35em;margin-top:-.05em;margin-left:-1.35em}.nav-item.is-active>.nav-item-toggle{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.is-current-page>.nav-link,.is-current-page>.nav-text{font-weight:600}.nav-panel-explore{background:#eaf0f3;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;position:absolute;top:0;right:0;bottom:0;left:0}.nav-panel-explore:not(:first-child){top:auto;max-height:calc(50% + 2.8125rem)}.nav-panel-explore .context{font-size:.9375rem;-ms-flex-negative:0;flex-shrink:0;color:#5d5d5d;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;line-height:1;height:2.8125rem}.nav-panel-explore:not(:first-child) .context{cursor:pointer}.nav-panel-explore .context .version{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:inherit;-ms-flex-align:inherit;align-items:inherit}.nav-panel-explore .context .version::after{content:"";background:url(../img/chevron.svg) no-repeat 100%/auto 100%;width:1.25em;height:.75em}.nav-panel-explore .components{line-height:1.15;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-shadow:inset 0 1px 5px #eaf0f3;box-shadow:inset 0 1px 5px #eaf0f3;background:#f0f0f0;padding:.5rem .75rem 0;margin:0;overflow-y:scroll;-ms-scroll-chaining:none;overscroll-behavior:none;max-height:100%;display:block}.nav-panel-explore:not(.is-active) .components{display:none}.nav-panel-explore .component{display:block}.nav-panel-explore .component+.component{margin-top:.5rem}.nav-panel-explore .component:last-child{margin-bottom:.75rem}.nav-panel-explore .component .title{font-weight:600}.nav-panel-explore .versions{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-top:-.25rem;line-height:1;list-style:none}.nav-panel-explore .component .version{margin:.375rem .375rem 0 0}.nav-panel-explore .component .version a{border:1px solid #c1c1c1;border-radius:.25rem;opacity:.75;white-space:nowrap;padding:.125em .25em;display:inherit}.nav-panel-explore .component .is-current a{border-color:currentColor;opacity:.9;font-weight:600}@media screen and (max-width:1023.5px){aside.toc.sidebar{display:none}main>.content{overflow-x:auto}}@media screen and (min-width:1024px){main{-webkit-box-flex:1;-ms-flex:auto;flex:auto;min-width:0}main>.content{display:-webkit-box;display:-ms-flexbox;display:flex}aside.toc.embedded{display:none}aside.toc.sidebar{-webkit-box-flex:0;-ms-flex:0 0 10.125rem;flex:0 0 10.125rem;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}}@media screen and (min-width:1216px){aside.toc.sidebar{-ms-flex-preferred-size:13.5rem;flex-basis:13.5rem}}.toolbar{color:#5d5d5d;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#eaf0f3;-webkit-box-shadow:0 1px 0 #eaf0f3;box-shadow:0 1px 0 #eaf0f3;font-size:.9375rem;height:2.8125rem;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;position:sticky;top:var(--navbar-height);z-index:2}.toolbar a{color:inherit}.nav-toggle{background:url(../img/menu.svg) no-repeat 50% 47.5%;background-size:49%}.dark .nav-toggle,.nav-toggle{border:none;outline:none;line-height:inherit;padding:0;height:2.8125rem;width:2.8125rem;margin-right:-.25rem}.dark .nav-toggle{background:url(../img/dark-menu.svg) no-repeat 50% 47.5%;background-size:49%}@media screen and (min-width:1024px){.nav-toggle{display:none}}.nav-toggle.is-active{background-image:url(../img/back.svg);background-size:41.5%}.home-link{display:block;background:url(../img/home-o.svg) no-repeat 50%;height:1.40625rem;width:1.40625rem;margin:.70313rem}.home-link.is-current,.home-link:hover{background-image:url(../img/home.svg)}.edit-this-page{display:none;padding-right:.5rem}@media screen and (min-width:1024px){.edit-this-page{display:block}}.toolbar .edit-this-page a{color:#8e8e8e}.breadcrumbs{display:none;-webkit-box-flex:1;-ms-flex:1 1;flex:1 1;padding:0 .5rem 0 .75rem;font-size:.7rem;line-height:1.35}@media screen and (min-width:1024px){.breadcrumbs{display:block}}a+.breadcrumbs{padding-left:.05rem}.breadcrumbs ul{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0;padding:0;list-style:none}.breadcrumbs li{display:inline;margin:0}.breadcrumbs li::after{content:"/";padding:0 .5rem}.breadcrumbs li:last-of-type::after{content:none}.page-versions{margin:0 .2rem 0 auto;position:relative;line-height:1}@media screen and (min-width:1024px){.page-versions{margin-right:.7rem}}.page-versions .version-menu-toggle{color:inherit;background:url(../img/chevron.svg) no-repeat;background-position:right .5rem top 50%;background-size:auto .75em;border:none;outline:none;line-height:inherit;padding:.5rem 1.5rem .5rem .5rem;position:relative;z-index:3}.page-versions .version-menu{display:-webkit-box;display:-ms-flexbox;display:flex;min-width:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;background:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#f0f0f0)) no-repeat;background:linear-gradient(180deg,#f0f0f0 0,#f0f0f0) no-repeat;padding:1.375rem 1.5rem .5rem .5rem;position:absolute;top:0;right:0;white-space:nowrap}.page-versions:not(.is-active) .version-menu{display:none}.page-versions .version{display:block;padding-top:.5rem}.page-versions .version.is-current{display:none}.page-versions .version.is-missing{color:#8e8e8e;font-style:italic;text-decoration:none}.toc-menu{color:#5d5d5d}.toc.sidebar .toc-menu{margin-right:.75rem;position:sticky;top:calc(var(--navbar-height) + 2.8125rem)}.toc .toc-menu h3{color:#000;font-size:1rem;font-weight:600;line-height:1.3;margin:0 -.5px;padding-bottom:.25rem}.toc.sidebar .toc-menu h3{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:2.5rem;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.toc .toc-menu ul{font-size:.9375rem;line-height:1.2;list-style:none;margin:0;padding:0}.toc.sidebar .toc-menu ul{max-height:calc(100vh - var(--navbar-height) - 5.3125rem);overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:none}@supports (scrollbar-width:none){.toc.sidebar .toc-menu ul{scrollbar-width:none}}.toc .toc-menu ul::-webkit-scrollbar{width:0;height:0}@media screen and (min-width:1024px){.toc .toc-menu h3{font-size:.9375rem}.toc .toc-menu ul{font-size:.84375rem}}.toc .toc-menu li{margin:0}.toc .toc-menu li[data-level="2"] a{padding-left:1.25rem}.toc .toc-menu li[data-level="3"] a{padding-left:2rem}.toc .toc-menu a{color:inherit;border-left:2px solid #eaf0f3;display:inline-block;padding:.25rem 0 .25rem .5rem;text-decoration:none}.sidebar.toc .toc-menu a{display:block;outline:none}.toc .toc-menu a:hover{color:#1565c0}.toc .toc-menu a.is-active{border-left-color:#1565c0;color:#000}.sidebar.toc .toc-menu a:focus{background:#eaf0f3}.toc .toc-menu .is-hidden-toc{display:none!important}.doc{color:#000;font-family:Noto Sans,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;line-height:1.15;margin:0 auto;max-width:45rem}@media screen and (min-width:1024px){.doc{-webkit-box-flex:1;-ms-flex:auto;flex:auto;font-size:.83333rem;margin:0 2rem;max-width:51.75rem;min-width:0}}.doc h1,.doc h2,.doc h3,.doc h4,.doc h5,.doc h6{color:#000;font-weight:600;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;line-height:1.3;margin:1rem 0 0;font-size:revert}.doc>h1.page:first-child{font-size:1.375rem;margin:1.5rem 0}@media screen and (min-width:769px){.doc>h1.page:first-child{margin-top:2.5rem}}.doc>h1.page:first-child+aside.toc.embedded{margin-top:-.5rem}.doc>h2#name+.sectionbody{margin-top:1rem}#preamble+.sect1,.doc .sect1+.sect1{margin-top:2rem}.doc h1.sect0{background:#f0f0f0;font-size:1.8em;margin:1.5rem -1rem 0;padding:.5rem 1rem}.doc h2:not(.discrete){border-bottom:1px solid #eaf0f3;margin-left:-1rem;margin-right:-1rem;padding:.4rem 1rem .1rem}.doc h3:not(.discrete),.doc h4:not(.discrete){font-weight:600}.doc h1 .anchor,.doc h2 .anchor,.doc h3 .anchor,.doc h4 .anchor,.doc h5 .anchor,.doc h6 .anchor{position:absolute;text-decoration:none;width:1.75ex;margin-left:-1.5ex;visibility:hidden;font-size:.8em;font-weight:400;padding-top:.05em}.doc h1 .anchor::before,.doc h2 .anchor::before,.doc h3 .anchor::before,.doc h4 .anchor::before,.doc h5 .anchor::before,.doc h6 .anchor::before{content:"\00a7"}.doc h1:hover .anchor,.doc h2:hover .anchor,.doc h3:hover .anchor,.doc h4:hover .anchor,.doc h5:hover .anchor,.doc h6:hover .anchor{visibility:visible}.doc dl,.doc p{margin:0}.doc a{color:#1565c0}.doc a:hover{color:#104d92}.doc a.bare{-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}.doc a.unresolved{color:#d32f2f}.doc i.fa{-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;font-style:normal}.doc .colist>table code,.doc p code,.doc thead code{color:#314a57;background:#eaf0f3;border-radius:.25em;font-size:.95em;padding:.125em .25em}.doc code,.doc pre{-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}.doc pre{font-size:inherit;line-height:1.5;margin:0}.doc blockquote{margin:0}.doc .paragraph.lead>p{font-size:1.125rem}.doc .right{float:right}.doc .left{float:left}.doc .float-gap.right{margin:0 1rem 1rem 0}.doc .float-gap.left{margin:0 0 1rem 1rem}.doc .float-group::after{content:"";display:table;clear:both}.doc .stretch{width:100%}.doc .underline{text-decoration:underline}.doc .line-through{text-decoration:line-through}.doc .dlist,.doc .exampleblock,.doc .hdlist,.doc .imageblock,.doc .listingblock,.doc .literalblock,.doc .olist,.doc .paragraph,.doc .partintro,.doc .quoteblock,.doc .sidebarblock,.doc .tabs,.doc .ulist,.doc .verseblock,.doc .videoblock,.doc details,.doc hr{margin:1rem 0 0}.doc table.tableblock{font-size:inherit;border:0}.doc .tablecontainer,.doc .tablecontainer+*,.doc :not(.tablecontainer)>table.tableblock,.doc :not(.tablecontainer)>table.tableblock+*{margin-top:1.5rem}.doc p.tableblock+p.tableblock{margin-top:.5rem}.doc td.tableblock>.content>:first-child{margin-top:0}.doc table.tableblock td,.doc table.tableblock th{padding:.5rem}.doc table.tableblock tr th{background-color:#f0f0f0;border:1px solid #dcdcdc}.doc table.tableblock,.doc table.tableblock>*>tr>*{border:0 solid #dcdcdc}.doc table.grid-all>*>tr>*{border-width:1px}.doc table.grid-cols>*>tr>*{border-width:0 1px}.doc table.grid-rows>*>tr>*{border-width:1px 0}.doc table.grid-all>thead th,.doc table.grid-rows>thead th{border-bottom-width:1px}.doc table.frame-all{border-width:0}.doc table.frame-ends{border-width:1px 0}.doc table.frame-sides{border-width:0 1px}.doc table.frame-none>colgroup+*>:first-child>*,.doc table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}.doc table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}.doc table.frame-ends>*>tr>:first-child,.doc table.frame-none>*>tr>:first-child{border-left-width:0}.doc table.frame-ends>*>tr>:last-child,.doc table.frame-none>*>tr>:last-child{border-right-width:0}.doc table.stripes-all>tbody>tr,.doc table.stripes-even>tbody>tr:nth-of-type(2n),.doc table.stripes-hover>tbody>tr:hover,.doc table.stripes-odd>tbody>tr:nth-of-type(odd){background:#eaf0f3}.doc table.tableblock>tfoot{background:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#fff));background:linear-gradient(180deg,#f0f0f0 0,#fff)}.doc .halign-left{text-align:left}.doc .halign-right{text-align:right}.doc .halign-center{text-align:center}.doc .valign-top{vertical-align:top}.doc .valign-bottom{vertical-align:bottom}.doc .valign-middle{vertical-align:middle}.doc .admonitionblock{margin:1.4rem 0 0;padding:1rem;background:#fff;border:1px solid #dcdcdc}.doc .admonitionblock p,.doc .admonitionblock td.content{font-size:inherit}.doc .admonitionblock td.content>.title+*,.doc .admonitionblock td.content>:not(.title):first-child{margin-top:0}.doc .admonitionblock pre{font-size:inherit}.doc .admonitionblock>table{table-layout:fixed;position:relative;width:100%}.doc .admonitionblock>table tr{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;gap:.25em}.doc .admonitionblock td.content{padding:0 1.7rem;width:100%;word-wrap:anywhere}.doc .admonitionblock .icon{font-size:inherit;padding:0 0 0 1.25rem;line-height:1;font-weight:600;color:#000!important;min-height:1.25rem}.doc .admonitionblock.caution .icon{color:#fff;background:no-repeat url(../img/caution.svg)}.doc .admonitionblock.important .icon{color:#fff;background:no-repeat url(../img/important.svg)}.doc .admonitionblock.note .icon{color:#fff;background:no-repeat url(../img/note.svg)}.doc .admonitionblock.tip .icon{color:#fff;background:no-repeat url(../img/tip.svg)}.doc .admonitionblock.warning .icon{color:#fff;background:no-repeat url(../img/warning.svg)}.doc .admonitionblock .icon i{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;padding:0 .35rem}.doc .admonitionblock .icon i::after{content:attr(title)}.doc .imageblock,.doc .videoblock{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.doc .imageblock.text-left,.doc .videoblock.text-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.doc .imageblock.text-right,.doc .videoblock.text-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.doc .image>img,.doc .image>object,.doc .image>svg,.doc .imageblock img,.doc .imageblock object,.doc .imageblock svg{display:inline-block;height:auto;max-width:100%;vertical-align:middle}.doc .imageblock .mermaid.content{width:100%}.doc .image:not(.left):not(.right)>img{margin-top:-.2em}.doc .videoblock iframe{max-width:100%;vertical-align:middle}#preamble .abstract blockquote{background:#f0f0f0;border-left:5px solid #eaf0f3;color:#4a4a4a;font-size:1rem;padding:.75em 1em}.doc .quoteblock,.doc .verseblock{background:#fefefe;border-left:3px solid #5d5d5d;color:#5d5d5d}.doc .quoteblock{padding:.25rem 1.5rem 1.25rem}.doc .quoteblock .attribution{color:#8e8e8e;font-size:inherit;margin-top:.75rem}.doc .quoteblock blockquote{margin-top:1rem}.doc .quoteblock .paragraph{font-style:italic}.doc .quoteblock cite{padding-left:1em}.doc .verseblock{font-size:inherit;padding:1rem 2rem}.doc .verseblock pre{font-family:inherit;font-size:inherit}.doc ol,.doc ul{margin:0;padding:0 0 0 2rem}.doc ul{list-style-type:disc}.doc ol.none,.doc ol.unnumbered,.doc ol.unstyled,.doc ul.checklist,.doc ul.no-bullet,.doc ul.none,.doc ul.unstyled{list-style-type:none}.doc ol.unnumbered,.doc ul.no-bullet{padding-left:1.25rem}.doc ol.unstyled,.doc ul.unstyled{padding-left:0}.doc ul.circle{list-style-type:circle}.doc ul.disc{list-style-type:disc}.doc ul.square{list-style-type:square}.doc ul.circle ul:not([class]),.doc ul.disc ul:not([class]),.doc ul.square ul:not([class]){list-style:inherit}.doc ol.arabic{list-style-type:decimal}.doc ol.decimal{list-style-type:decimal-leading-zero}.doc ol.loweralpha{list-style-type:lower-alpha}.doc ol.upperalpha{list-style-type:upper-alpha}.doc ol.lowerroman{list-style-type:lower-roman}.doc ol.upperroman{list-style-type:upper-roman}.doc ol.lowergreek{list-style-type:lower-greek}.doc ul.checklist{padding-left:1.75rem}.doc ul.checklist p>i.fa-check-square-o:first-child,.doc ul.checklist p>i.fa-square-o:first-child{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:1.25rem;margin-left:-1.25rem}.doc ul.checklist i.fa-check-square-o::before{content:"\2713"}.doc ul.checklist i.fa-square-o::before{content:"\274f"}.doc .dlist .dlist,.doc .dlist .olist,.doc .dlist .ulist,.doc .olist .dlist,.doc .olist .olist,.doc .olist .ulist,.doc .olist li+li,.doc .ulist .dlist,.doc .ulist .olist,.doc .ulist .ulist,.doc .ulist li+li{margin-top:.5rem}.doc .admonitionblock .listingblock,.doc .olist .listingblock,.doc .ulist .listingblock{padding:0}.doc .admonitionblock .title,.doc .exampleblock .title,.doc .imageblock .title,.doc .listingblock .title,.doc .literalblock .title,.doc .openblock .title,.doc .tableblock caption,.doc .videoblock .title{color:#5d5d5d;font-size:inherit;font-style:italic;font-weight:600;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;letter-spacing:.01em;padding-bottom:.35rem}.doc .tableblock caption{text-align:left}.doc .olist .title,.doc .ulist .title{font-style:italic;font-weight:600;margin-bottom:.25rem}.doc .imageblock .title{margin-top:.5rem;padding-bottom:0}.doc details{margin-left:1rem}.doc details>summary{display:block;position:relative;line-height:1.15;margin-bottom:.5rem}.doc details>summary::-webkit-details-marker{display:none}.doc details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.275em;left:-1rem;-webkit-transform:translateX(15%);transform:translateX(15%)}.doc details[open]>summary::before{border-color:currentColor transparent transparent;border-width:.5rem .3rem 0;-webkit-transform:translateY(15%);transform:translateY(15%)}.doc details>summary::after{content:"";width:1rem;height:1em;position:absolute;top:.075em;left:-1rem}.doc details.result{margin-top:.25rem}.doc details.result>summary{color:#5d5d5d;font-style:italic;margin-bottom:0}.doc details.result>.content{margin-left:-1rem}.doc .exampleblock>.content,.doc details.result>.content{background:#fff;border:.125rem solid #5d5d5d;border-radius:0;padding:.75rem}.doc .exampleblock>.content::after,.doc details.result>.content::after{content:"";display:table;clear:both}.doc .exampleblock>.content>:first-child,.doc details>.content>:first-child{margin-top:0}.doc .sidebarblock{background:#eaf0f3;border-radius:.75rem;padding:.75rem 1.5rem}.doc .sidebarblock>.content>.title{font-size:1.40625rem;font-weight:600;line-height:1.3;margin-bottom:-.3em;text-align:center}.doc .sidebarblock>.content>:not(.title):first-child{margin-top:0}.doc .listingblock.wrap pre,.doc .tableblock pre{white-space:pre-wrap}.doc .listingblock pre:not(.highlight),.doc .literalblock pre,.doc pre.highlight code{background:none;border:1px solid #dcdcdc;display:block;overflow-x:auto;padding:.685em;font-size:inherit}.doc .listingblock>.content{position:relative}.doc .source-toolbox{display:-webkit-box;display:-ms-flexbox;display:flex;visibility:hidden;position:absolute;top:.25rem;right:.5rem;color:grey;font-family:Noto Sans,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:.8125rem;line-height:1;white-space:nowrap;z-index:1}.doc .listingblock:hover .source-toolbox{visibility:visible}.doc .source-toolbox .source-lang{text-transform:uppercase;letter-spacing:.075em}.doc .source-toolbox>:not(:last-child)::after{content:"|";letter-spacing:0;padding:0 1ch}.doc .source-toolbox .copy-button{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:none;border:none;color:inherit;outline:none;padding:0;font-size:inherit;line-height:inherit;width:1em;height:1em}.doc .source-toolbox .copy-icon{-webkit-box-flex:0;-ms-flex:none;flex:none;width:inherit;height:inherit}.doc .source-toolbox img.copy-icon{-webkit-filter:invert(50.2%);filter:invert(50.2%)}.doc .source-toolbox svg.copy-icon{fill:currentColor}.doc .source-toolbox .copy-toast{-webkit-box-flex:0;-ms-flex:none;flex:none;position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-top:1em;background-color:#000;border-radius:.25em;padding:.5em;color:#fff;cursor:auto;opacity:0;-webkit-transition:opacity .5s ease .5s;transition:opacity .5s ease .5s}.doc .source-toolbox .copy-toast::after{content:"";position:absolute;top:0;width:1em;height:1em;border:.55em solid transparent;border-left-color:#000;-webkit-transform:rotate(-90deg) translateX(50%) translateY(50%);transform:rotate(-90deg) translateX(50%) translateY(50%);-webkit-transform-origin:left;transform-origin:left}.doc .source-toolbox .copy-button.clicked .copy-toast{opacity:1;-webkit-transition:none;transition:none}.doc .language-console .hljs-meta{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.doc .dlist dt{font-style:italic}.doc .dlist dd{margin:0 0 .25rem 1.5rem}.doc .dlist dd:last-of-type{margin-bottom:0}.doc td.hdlist1,.doc td.hdlist2{padding:.5rem 0 0;vertical-align:top}.doc tr:first-child>.hdlist1,.doc tr:first-child>.hdlist2{padding-top:0}.doc td.hdlist1{font-weight:600;padding-right:.25rem}.doc td.hdlist2{padding-left:.25rem}.doc .colist{font-size:1rem;margin:.25rem 0 -.25rem}.doc .colist>table>tbody>tr>:first-child,.doc .colist>table>tr>:first-child{padding:.25em .5rem 0;vertical-align:top}.doc .colist>table>tbody>tr>:last-child,.doc .colist>table>tr>:last-child{padding:.25rem 0}.doc .conum[data-value]{border:1px solid;border-radius:100%;display:inline-block;font-family:Noto Sans,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:.84375rem;font-style:normal;line-height:1.2;text-align:center;width:1.25em;height:1.25em;letter-spacing:-.25ex;text-indent:-.25ex}.doc .conum[data-value]::after{content:attr(data-value)}.doc .conum[data-value]+b{display:none}.doc hr{border:solid #eaf0f3;border-width:2px 0 0;height:0}.doc b.button{white-space:nowrap}.doc b.button::before{content:"[";padding-right:.25em}.doc b.button::after{content:"]";padding-left:.25em}.doc kbd{display:inline-block;font-size:.75rem;background:#eaf0f3;border:1px solid #c1c1c1;border-radius:.25em;-webkit-box-shadow:0 1px 0 #c1c1c1,0 0 0 .1em #fff inset;box-shadow:0 1px 0 #c1c1c1,inset 0 0 0 .1em #fff;padding:.25em .5em;vertical-align:text-bottom;white-space:nowrap}.doc .keyseq,.doc kbd{line-height:1}.doc .keyseq{font-size:1rem}.doc .keyseq kbd{margin:0 .125em}.doc .keyseq kbd:first-child{margin-left:0}.doc .keyseq kbd:last-child{margin-right:0}.doc .menuseq,.doc .path{-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}.doc .menuseq i.caret::before{content:"\203a";font-size:1.1em;font-weight:600;line-height:.90909}.doc :not(pre).nowrap{white-space:nowrap}.doc .nobreak{-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;word-wrap:normal}#footnotes{font-size:.85em;line-height:1.5;margin:2rem -.5rem 0}.doc td.tableblock>.content #footnotes{margin:2rem 0 0}#footnotes hr{border-top-width:1px;margin-top:0;width:20%}#footnotes .footnote{margin:.5em 0 0 1em}#footnotes .footnote+.footnote{margin-top:.25em}#footnotes .footnote>a:first-of-type{display:inline-block;margin-left:-2em;text-align:right;width:1.5em}nav.pagination{display:-webkit-box;display:-ms-flexbox;display:flex;border-top:1px solid #eaf0f3;line-height:1;margin:2rem -1rem -1rem;padding:.75rem 1rem 0}.dark nav.pagination{border-top:1px solid var(#051a26)}nav.pagination span{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:50%;-ms-flex:50%;flex:50%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}nav.pagination .prev{padding-right:.5rem}nav.pagination .next{margin-left:auto;padding-left:.5rem;text-align:right}nav.pagination span::before{color:#8e8e8e;font-size:.75em;padding-bottom:.1em}nav.pagination .prev::before{content:"Prev"}nav.pagination .next::before{content:"Next"}nav.pagination a{font-weight:600;line-height:1.3;position:relative}nav.pagination a::after,nav.pagination a::before{color:#8e8e8e;font-weight:400;font-size:1.5em;line-height:.75;position:absolute;top:0;width:1rem}nav.pagination .prev a::before{content:"\2039";-webkit-transform:translateX(-100%);transform:translateX(-100%)}nav.pagination .next a::after{content:"\203a"}.spirit-nav{text-align:right;padding-top:.5em}.spirit-nav a{color:#fff;padding-left:.5em;display:inline-block;vertical-align:middle}.spirit-nav img{border-width:0;vertical-align:middle}.spirit-nav .disabled{opacity:.35;cursor:not-allowed;pointer-events:none}html.is-clipped--navbar{overflow-y:hidden}.navbar{background:#eaf0f3;color:#314a57;font-size:1rem;height:var(--navbar-height);position:fixed;top:0;width:100%;z-index:4;border-bottom:2px solid #d1d5db}.navbar a{text-decoration:none}.navbar-brand{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:auto;flex:auto;padding-left:1rem}.navbar-brand .navbar-item{color:#314a57}.navbar-brand .navbar-item:first-child{-ms-flex-item-align:center;align-self:center;padding:0;font-size:1.375rem;-ms-flex-wrap:wrap;flex-wrap:wrap;line-height:1}.navbar-brand .navbar-item:first-child a{color:inherit;word-wrap:normal}.navbar-brand .navbar-item:first-child :not(:last-child){padding-right:.375rem}.navbar-brand .navbar-item.search{-webkit-box-flex:1;-ms-flex:auto;flex:auto;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}#search-input{color:#333;font-family:inherit;font-size:.95rem;width:150px;border:1px solid #dbdbdb;border-radius:.1em;line-height:1.5;padding:0 .25em}#search-input:disabled{background-color:#dbdbdb;cursor:not-allowed;pointer-events:all!important}#search-input:disabled::-webkit-input-placeholder{color:#4c4c4c}#search-input:disabled::-moz-placeholder{color:#4c4c4c}#search-input:disabled:-ms-input-placeholder{color:#4c4c4c}#search-input:disabled::-ms-input-placeholder{color:#4c4c4c}#search-input:disabled::placeholder{color:#4c4c4c}#search-input:focus{outline:none}.navbar-burger{background:none;border:none;outline:none;line-height:1;position:relative;width:3rem;padding:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-left:auto;min-width:0}.navbar-burger span{background-color:#314a57;height:1.5px;width:1rem}.navbar-burger:not(.is-active) span{-webkit-transition:opacity 0s .25s,margin-top .25s ease-out .25s,-webkit-transform .25s ease-out;transition:opacity 0s .25s,margin-top .25s ease-out .25s,-webkit-transform .25s ease-out;transition:transform .25s ease-out,opacity 0s .25s,margin-top .25s ease-out .25s;transition:transform .25s ease-out,opacity 0s .25s,margin-top .25s ease-out .25s,-webkit-transform .25s ease-out}.navbar-burger span+span{margin-top:.25rem}.navbar-burger.is-active span+span{margin-top:-1.5px}.navbar-burger.is-active span:first-child{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.navbar-item,.navbar-link{color:#314a57;display:block;line-height:1.15;padding:.5rem 1rem}.navbar-item.has-dropdown{padding:0}.navbar-item .icon{width:1.25rem;height:1.25rem;display:block}.navbar-item .icon img,.navbar-item .icon svg{fill:currentColor;width:inherit;height:inherit}.navbar-link{padding-right:2.5em}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-dropdown .navbar-item.has-label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.navbar-dropdown .navbar-item small{color:#8e8e8e;font-size:.75rem}.navbar-divider{background-color:#eaf0f3;border:none;height:1px;margin:.25rem 0}.navbar .button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#fff;border:1px solid #eaf0f3;border-radius:.15rem;height:1.75rem;color:#314a57;padding:0 .75em;white-space:nowrap}@media screen and (max-width:768.5px){.navbar-brand .navbar-item.search{padding-left:0;padding-right:0}}@media screen and (min-width:769px){#search-input{width:200px}}@media screen and (max-width:1023.5px){.navbar-brand{height:inherit}.navbar-brand .navbar-item{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.navbar-menu{background:#fff;-webkit-box-shadow:0 8px 16px rgba(10,10,10,.1);box-shadow:0 8px 16px rgba(10,10,10,.1);max-height:calc(100vh - var(--navbar-height));overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:none;padding:.5rem 0}.navbar-menu:not(.is-active){display:none}.navbar-menu .navbar-link:hover,.navbar-menu a.navbar-item:hover{background:#eaf0f3}}@media screen and (min-width:1024px){.navbar-burger{display:none}.navbar,.navbar-end,.navbar-item,.navbar-link,.navbar-menu{display:-webkit-box;display:-ms-flexbox;display:flex}.navbar-item,.navbar-link{position:relative;-webkit-box-flex:0;-ms-flex:none;flex:none}.navbar-item:not(.has-dropdown),.navbar-link{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar-link::after{border-width:0 0 1px 1px;border-style:solid;content:"";display:block;height:.5em;pointer-events:none;position:absolute;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:.5em;margin-top:-.375em;right:1.125em;top:50%}.navbar-end .navbar-link,.navbar-end>.navbar-item{color:#314a57}.navbar-end .navbar-item.has-dropdown:hover .navbar-link,.navbar-end .navbar-link:hover,.navbar-end>a.navbar-item:hover{background:#eaf0f3;color:#314a57}.navbar-end .navbar-link::after{border-color:currentColor}.navbar-dropdown{background:#fff;border:1px solid #eaf0f3;border-top:none;border-radius:0 0 .25rem .25rem;display:none;top:100%;left:0;min-width:100%;position:absolute}.navbar-dropdown .navbar-item{padding:.5rem 3rem .5rem 1rem;white-space:nowrap}.navbar-dropdown .navbar-item small{position:relative;right:-2rem}.navbar-dropdown .navbar-item:last-child{border-radius:inherit}.navbar-dropdown.is-right{left:auto;right:0}.navbar-dropdown a.navbar-item:hover{background:#eaf0f3}}footer.footer{background-color:#eaf0f3;color:#5d5d5d;font-size:.9375rem;line-height:1.15;padding:.5rem 1.5rem}.footer p{margin:0}.footer a{color:#314a57} +/*! Adapted from the GitHub style by Vasily Polovnyov */.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:500}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:500}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:500}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:500}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:500}html.dark .hljs,html.dark pre{color:#abb2bf}html.dark .hljs-comment,html.dark .hljs-quote{color:#5c6370;font-style:italic}html.dark .hljs-keyword,html.dark .hljs-selector-tag,html.dark .hljs-subst{color:#c678dd}html.dark .hljs-doctag,html.dark .hljs-regexp,html.dark .hljs-string{color:#98c379}html.dark .hljs-literal,html.dark .hljs-number,html.dark .hljs-tag .hljs-attr,html.dark .hljs-template-variable,html.dark .hljs-variable{color:#d19a66}html.dark .hljs-section,html.dark .hljs-selector-id,html.dark .hljs-title{color:#61aeee}html.dark .hljs-class .hljs-title,html.dark .hljs-type{color:#e6c07b}html.dark .hljs-name,html.dark .hljs-tag{color:#e06c75}html.dark .hljs-attribute{color:#d19a66}html.dark .hljs-link{color:#61aeee}html.dark .hljs-bullet,html.dark .hljs-symbol{color:#d19a66}html.dark .hljs-built_in,html.dark .hljs-builtin-name{color:#56b6c2}html.dark .hljs-meta{color:#61aeee}html.dark .hljs-deletion{color:#e06c75;background:rgba(224,108,117,.15)}html.dark .hljs-addition{color:#98c379;background:rgba(152,195,121,.15)}html.dark .hljs-params{color:#abb2bf}html.dark .hljs-selector-class{color:#d19a66}html.dark .hljs-template-tag{color:#c678dd}.doc pre.highlight code.cpp-highlight .cpp-keyword,code.cpp-highlight .cpp-keyword{color:#00f}.doc pre.highlight code.cpp-highlight .cpp-string,code.cpp-highlight .cpp-string{color:#a31515}.doc pre.highlight code.cpp-highlight .cpp-preprocessor,code.cpp-highlight .cpp-preprocessor{color:#6f008a}.doc pre.highlight code.cpp-highlight .cpp-comment,code.cpp-highlight .cpp-comment{color:green;font-style:italic}.doc pre.highlight code.cpp-highlight .cpp-attribute,code.cpp-highlight .cpp-attribute{color:#9e9e9e}.doc pre.highlight code.cpp-highlight,code.cpp-highlight{color:inherit}html.dark .doc pre.highlight code.cpp-highlight .cpp-keyword,html.dark code.cpp-highlight .cpp-keyword{color:#c678dd}html.dark .doc pre.highlight code.cpp-highlight .cpp-string,html.dark code.cpp-highlight .cpp-string{color:#98c379}html.dark .doc pre.highlight code.cpp-highlight .cpp-preprocessor,html.dark code.cpp-highlight .cpp-preprocessor{color:#e06c75}html.dark .doc pre.highlight code.cpp-highlight .cpp-comment,html.dark code.cpp-highlight .cpp-comment{color:#5c6370;font-style:italic}html.dark .doc pre.highlight code.cpp-highlight .cpp-attribute,html.dark code.cpp-highlight .cpp-attribute{color:#d19a66}html.dark .doc pre.highlight code.cpp-highlight,html.dark code.cpp-highlight{color:#abb2bf}.theme-toggle{display:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;background:transparent;border:1px solid #e4e7ea;cursor:pointer;padding:.25rem;margin-left:1rem;margin-right:0;margin-bottom:.25rem;border-radius:.5rem;-webkit-transition:background-color .2s ease;transition:background-color .2s ease}.theme-toggle:hover .fas{color:#ff9f00}.theme-toggle:focus{outline:none}.theme-toggle .fas{font-size:16px;vertical-align:middle;color:#314a57}.theme-icon-dark{display:inline}.theme-icon-light,html.dark .theme-icon-dark{display:none}html.dark .theme-icon-light{display:inline}html.dark .theme-toggle{border-color:#333}html.dark .theme-toggle .fas{color:#f0f0ff}html.dark .theme-toggle:hover .fas{color:#ff9f00}@page{margin:.5in}@media print{.hide-for-print{display:none!important}html{font-size:.9375rem}a{color:inherit!important;text-decoration:underline}a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none}img,object,svg,tr{page-break-inside:avoid}thead{display:table-header-group}pre{-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre-wrap}body{padding-top:2rem}.navbar{background:none;color:inherit;position:absolute}.navbar *{color:inherit!important}.nav-container,.navbar>:not(.navbar-brand),.toolbar,aside.toc,nav.pagination{display:none}.doc{color:inherit;margin:auto;max-width:none;padding-bottom:2rem}.doc .admonitionblock td.icon{-webkit-print-color-adjust:exact;color-adjust:exact}.doc .listingblock code[data-lang]::before{display:block}footer.footer{background:none;border-top:1px solid #eaf0f3;color:#8e8e8e;padding:.25rem .5rem 0}.footer *{color:inherit}} +/*! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com*/*,::after,::before{-webkit-box-sizing:border-box;box-sizing:border-box;border:0 solid #e5e7eb}::after,::before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;-webkit-font-feature-settings:normal;font-feature-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{opacity:1;color:#9ca3af}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::-ms-input-placeholder,textarea::-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::after,::before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-webkit-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.static{position:static}.relative{position:relative}.sticky{position:sticky}.block{display:block}.inline{display:inline}.inline-flex{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.table{display:table}.contents{display:contents}.resize{resize:both}.italic{font-style:italic}body,html{height:100%;min-height:100vh}html.is-clipped--nav{overflow-y:visible}@media screen and (min-width:769px){.body{display:-webkit-box;display:-ms-flexbox;display:flex;padding:1rem 1rem 0}}body.article{background-color:#e5e7eb}.max-width-reset{max-width:none}.dark .nav-link,.dark .nav-menu a,.dark .nav-text{color:#ccc}html.is-clipped--nav div#content{display:none;visibility:hidden}html:not(.is-clipped--nav) div#content{display:block;visibility:visible}@media screen and (max-width:768px){.content{width:100%}}@media screen and (min-width:1024px){.doc{margin:0}}aside.nav{position:static;background-color:#fff;-webkit-box-shadow:none;box-shadow:none;height:auto;overflow-y:auto}.dark aside.nav,.dark div.toolbar{background-color:transparent!important}html.is-clipped--nav .nav-close{display:block;visibility:visible}.nav .panels{height:auto}.nav-list{margin-left:0}.nav-list>.nav-list{margin-left:1rem}.nav-menu{padding:0}.nav-panel-menu{overflow-y:auto}.nav-toggle.is-active~.spirit-nav{display:none;visibility:hidden}.nav-toggle{background-position-x:0;background-position-y:50%}.nav-close{display:none;background:url(../img/back.svg) 0 40% no-repeat;background-size:41.5%;border:none;outline:none;line-height:inherit;padding:0;height:2rem;width:3rem;margin-right:-.25rem}.dark .nav-close{background:url(../img/dark-back.svg) 0 40% no-repeat;background-size:41.5%}.nav-container.is-active{position:static;padding:.5rem 1rem 2rem}.nav-link,.nav-menu a,.nav-text{color:#000}@media screen and (min-width:769px){.nav-toggle{display:none;visibility:hidden}.nav-toggle.is-active~.spirit-nav{display:block;visibility:visible}.nav-container{position:sticky;top:1rem;bottom:1rem;left:1rem;height:calc(100vh - 2rem);visibility:visible;min-width:16rem;overflow-y:auto;font-size:1rem!important}.nav-container.is-active{padding-left:1rem;padding-top:1rem}}.toolbar{background-color:#fff;-webkit-box-shadow:unset;box-shadow:unset;height:2rem;position:static;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:100%}.dark div.toolbar{background-color:#08283a}.toolbar .material-symbols-outlined{font-variation-settings:"FILL" 1,"wght" 700,"GRAD" 200,"opsz" 20!important;color:#000;font-size:18px}.dark .toolbar .material-symbols-outlined{color:#fff}@media screen and (min-width:769px){.toolbar{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}}@media screen and (min-width:1024px){.toolbar{-webkit-box-align:center;-ms-flex-align:center;align-items:center}}.breadcrumbs,.toolbar .breadcrumbs ul{padding-left:0}.breadcrumbs a{color:#424242;font-weight:500}.breadcrumbs li::after{padding:0 .25rem}@media screen and (min-width:769px){.breadcrumbs{display:block;visibility:visible}}.edit-this-page{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-top:2rem;padding:0}.spirit-nav{padding-top:0}.spirit-nav a{width:1.5rem}.toc.sidebar .toc-menu{top:0}.toc.sidebar{height:-webkit-fit-content;height:-moz-fit-content;height:fit-content}.toc.sidebar .toc-menu h3{height:auto;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;color:#424242}.toc.embedded{padding-top:.5rem}nav.pagination{padding:1rem}nav.pagination a::after,nav.pagination a::before{width:.75rem}.topnavbar+div.body{margin-left:auto;margin-right:auto;max-width:80rem} \ No newline at end of file diff --git a/preview/_/css/vendor/tabs.css b/preview/_/css/vendor/tabs.css new file mode 100644 index 0000000..27438a4 --- /dev/null +++ b/preview/_/css/vendor/tabs.css @@ -0,0 +1 @@ +/*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */.tabs{margin-bottom:1.25em}.tablist>ul{-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0}.tablist>ul,.tablist>ul li{display:-webkit-box;display:-ms-flexbox;display:flex}.tablist>ul li{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;cursor:pointer;font-weight:700;line-height:1.5;padding:.25em 1em;position:relative}.tablist>ul li:focus-visible{outline:none}.tablist.ulist,.tablist.ulist>ul li{margin:0}.tablist.ulist>ul li+li{margin-left:.25em}.tabs.is-loading .tablist li:not(:first-child),.tabs:not(.is-loading) .tablist li:not(.is-selected){background-color:#f5f5f5}.tabs.is-loading .tablist li:first-child::after,.tabs:not(.is-loading) .tablist li.is-selected::after{background-color:inherit;content:"";display:block;height:3px;position:absolute;bottom:-1.5px;left:0;right:0}.tablist>ul p{line-height:inherit;margin:0}.tabpanel{background-color:#fff;padding:1.25em}.tablist>ul li,.tabpanel{border:1px solid #dcdcdc}.tablist>ul li{border-bottom:0}.tabs.is-loading .tabpanel+.tabpanel,.tabs:not(.is-loading) .tabpanel.is-hidden{display:none}.tabpanel>:first-child{margin-top:0}#content .tabpanel>:last-child,#content .tabpanel>:last-child>:last-child,#content .tabpanel>:last-child>:last-child>li:last-child>:last-child{margin-bottom:0}.tablecontainer{overflow-x:auto}#content .tablecontainer{margin-bottom:1.25em}#content .tablecontainer>table.tableblock{margin-bottom:0} \ No newline at end of file diff --git a/preview/_/font/MonaSansDisplaySemiCondensed-Medium.ttf b/preview/_/font/MonaSansDisplaySemiCondensed-Medium.ttf new file mode 100644 index 0000000..90dddab Binary files /dev/null and b/preview/_/font/MonaSansDisplaySemiCondensed-Medium.ttf differ diff --git a/preview/_/font/MonaSansVF.ttf b/preview/_/font/MonaSansVF.ttf new file mode 100644 index 0000000..5d66dbf Binary files /dev/null and b/preview/_/font/MonaSansVF.ttf differ diff --git a/preview/_/font/MonaspaceNeon-Regular.otf b/preview/_/font/MonaspaceNeon-Regular.otf new file mode 100644 index 0000000..3119ba6 Binary files /dev/null and b/preview/_/font/MonaspaceNeon-Regular.otf differ diff --git a/preview/_/font/MonaspaceNeon-Var.woff2 b/preview/_/font/MonaspaceNeon-Var.woff2 new file mode 100644 index 0000000..9b7d48d Binary files /dev/null and b/preview/_/font/MonaspaceNeon-Var.woff2 differ diff --git a/preview/_/font/MonaspaceNeonFrozen-Regular.ttf b/preview/_/font/MonaspaceNeonFrozen-Regular.ttf new file mode 100644 index 0000000..f082376 Binary files /dev/null and b/preview/_/font/MonaspaceNeonFrozen-Regular.ttf differ diff --git a/preview/_/font/MonaspaceRadonFrozen-Italic.ttf b/preview/_/font/MonaspaceRadonFrozen-Italic.ttf new file mode 100644 index 0000000..ed0cf56 Binary files /dev/null and b/preview/_/font/MonaspaceRadonFrozen-Italic.ttf differ diff --git a/preview/_/font/MonaspaceXenon-Italic.otf b/preview/_/font/MonaspaceXenon-Italic.otf new file mode 100644 index 0000000..c4b9811 Binary files /dev/null and b/preview/_/font/MonaspaceXenon-Italic.otf differ diff --git a/preview/_/font/MonaspaceXenon-Var.woff2 b/preview/_/font/MonaspaceXenon-Var.woff2 new file mode 100644 index 0000000..3a92eb6 Binary files /dev/null and b/preview/_/font/MonaspaceXenon-Var.woff2 differ diff --git a/preview/_/font/MonaspaceXenonFrozen-Italic.ttf b/preview/_/font/MonaspaceXenonFrozen-Italic.ttf new file mode 100644 index 0000000..efd7bb3 Binary files /dev/null and b/preview/_/font/MonaspaceXenonFrozen-Italic.ttf differ diff --git a/preview/_/font/NotoSansDisplay-Italic.ttf b/preview/_/font/NotoSansDisplay-Italic.ttf new file mode 100644 index 0000000..bdeb0cc Binary files /dev/null and b/preview/_/font/NotoSansDisplay-Italic.ttf differ diff --git a/preview/_/font/NotoSansDisplay-Italic.woff2 b/preview/_/font/NotoSansDisplay-Italic.woff2 new file mode 100644 index 0000000..12e348d Binary files /dev/null and b/preview/_/font/NotoSansDisplay-Italic.woff2 differ diff --git a/preview/_/font/NotoSansDisplay.ttf b/preview/_/font/NotoSansDisplay.ttf new file mode 100644 index 0000000..04f51c4 Binary files /dev/null and b/preview/_/font/NotoSansDisplay.ttf differ diff --git a/preview/_/font/NotoSansDisplay.woff2 b/preview/_/font/NotoSansDisplay.woff2 new file mode 100644 index 0000000..598f431 Binary files /dev/null and b/preview/_/font/NotoSansDisplay.woff2 differ diff --git a/preview/_/font/NotoSansMono.ttf b/preview/_/font/NotoSansMono.ttf new file mode 100644 index 0000000..122ef75 Binary files /dev/null and b/preview/_/font/NotoSansMono.ttf differ diff --git a/preview/_/font/roboto-latin-400-italic.woff b/preview/_/font/roboto-latin-400-italic.woff new file mode 100644 index 0000000..ebee16b Binary files /dev/null and b/preview/_/font/roboto-latin-400-italic.woff differ diff --git a/preview/_/font/roboto-latin-400-italic.woff2 b/preview/_/font/roboto-latin-400-italic.woff2 new file mode 100644 index 0000000..e1b7a79 Binary files /dev/null and b/preview/_/font/roboto-latin-400-italic.woff2 differ diff --git a/preview/_/font/roboto-latin-400-normal.woff b/preview/_/font/roboto-latin-400-normal.woff new file mode 100644 index 0000000..9eaa94f Binary files /dev/null and b/preview/_/font/roboto-latin-400-normal.woff differ diff --git a/preview/_/font/roboto-latin-400-normal.woff2 b/preview/_/font/roboto-latin-400-normal.woff2 new file mode 100644 index 0000000..020729e Binary files /dev/null and b/preview/_/font/roboto-latin-400-normal.woff2 differ diff --git a/preview/_/font/roboto-latin-500-italic.woff b/preview/_/font/roboto-latin-500-italic.woff new file mode 100644 index 0000000..b6ad1c5 Binary files /dev/null and b/preview/_/font/roboto-latin-500-italic.woff differ diff --git a/preview/_/font/roboto-latin-500-italic.woff2 b/preview/_/font/roboto-latin-500-italic.woff2 new file mode 100644 index 0000000..ae1933f Binary files /dev/null and b/preview/_/font/roboto-latin-500-italic.woff2 differ diff --git a/preview/_/font/roboto-latin-500-normal.woff b/preview/_/font/roboto-latin-500-normal.woff new file mode 100644 index 0000000..d39bb52 Binary files /dev/null and b/preview/_/font/roboto-latin-500-normal.woff differ diff --git a/preview/_/font/roboto-latin-500-normal.woff2 b/preview/_/font/roboto-latin-500-normal.woff2 new file mode 100644 index 0000000..29342a8 Binary files /dev/null and b/preview/_/font/roboto-latin-500-normal.woff2 differ diff --git a/preview/_/font/roboto-mono-latin-400-normal.woff b/preview/_/font/roboto-mono-latin-400-normal.woff new file mode 100644 index 0000000..be3eb4c Binary files /dev/null and b/preview/_/font/roboto-mono-latin-400-normal.woff differ diff --git a/preview/_/font/roboto-mono-latin-400-normal.woff2 b/preview/_/font/roboto-mono-latin-400-normal.woff2 new file mode 100644 index 0000000..f8894ba Binary files /dev/null and b/preview/_/font/roboto-mono-latin-400-normal.woff2 differ diff --git a/preview/_/font/roboto-mono-latin-500-normal.woff b/preview/_/font/roboto-mono-latin-500-normal.woff new file mode 100644 index 0000000..43ca6a1 Binary files /dev/null and b/preview/_/font/roboto-mono-latin-500-normal.woff differ diff --git a/preview/_/font/roboto-mono-latin-500-normal.woff2 b/preview/_/font/roboto-mono-latin-500-normal.woff2 new file mode 100644 index 0000000..b4f2bf8 Binary files /dev/null and b/preview/_/font/roboto-mono-latin-500-normal.woff2 differ diff --git a/preview/_/img/Boost_Brandmark_WhiteBoost_Transparent.svg b/preview/_/img/Boost_Brandmark_WhiteBoost_Transparent.svg new file mode 100644 index 0000000..fe77a17 --- /dev/null +++ b/preview/_/img/Boost_Brandmark_WhiteBoost_Transparent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/Boost_Symbol_Transparent.svg b/preview/_/img/Boost_Symbol_Transparent.svg new file mode 100755 index 0000000..6320b86 --- /dev/null +++ b/preview/_/img/Boost_Symbol_Transparent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/arrow-left.svg b/preview/_/img/arrow-left.svg new file mode 100644 index 0000000..320f6c7 --- /dev/null +++ b/preview/_/img/arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/arrow-right.svg b/preview/_/img/arrow-right.svg new file mode 100644 index 0000000..8ae735a --- /dev/null +++ b/preview/_/img/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/arrow-up.svg b/preview/_/img/arrow-up.svg new file mode 100644 index 0000000..8c48c7a --- /dev/null +++ b/preview/_/img/arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/back.svg b/preview/_/img/back.svg new file mode 100644 index 0000000..bf7d30e --- /dev/null +++ b/preview/_/img/back.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/boost-logo-transparent.svg b/preview/_/img/boost-logo-transparent.svg new file mode 100644 index 0000000..b2ee587 --- /dev/null +++ b/preview/_/img/boost-logo-transparent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/caret.svg b/preview/_/img/caret.svg new file mode 100644 index 0000000..1af41bc --- /dev/null +++ b/preview/_/img/caret.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/caution.svg b/preview/_/img/caution.svg new file mode 100644 index 0000000..dfcb836 --- /dev/null +++ b/preview/_/img/caution.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/chevron.svg b/preview/_/img/chevron.svg new file mode 100644 index 0000000..40e962a --- /dev/null +++ b/preview/_/img/chevron.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/dark-back.svg b/preview/_/img/dark-back.svg new file mode 100644 index 0000000..b4bd3b1 --- /dev/null +++ b/preview/_/img/dark-back.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/dark-menu.svg b/preview/_/img/dark-menu.svg new file mode 100644 index 0000000..2c2345b --- /dev/null +++ b/preview/_/img/dark-menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/favicons/android-chrome-192x192.png b/preview/_/img/favicons/android-chrome-192x192.png new file mode 100644 index 0000000..16c1fbd Binary files /dev/null and b/preview/_/img/favicons/android-chrome-192x192.png differ diff --git a/preview/_/img/favicons/android-chrome-512x512.png b/preview/_/img/favicons/android-chrome-512x512.png new file mode 100644 index 0000000..d5f264b Binary files /dev/null and b/preview/_/img/favicons/android-chrome-512x512.png differ diff --git a/preview/_/img/favicons/apple-touch-icon.png b/preview/_/img/favicons/apple-touch-icon.png new file mode 100644 index 0000000..6c272bf Binary files /dev/null and b/preview/_/img/favicons/apple-touch-icon.png differ diff --git a/preview/_/img/favicons/favicon-16x16.png b/preview/_/img/favicons/favicon-16x16.png new file mode 100644 index 0000000..74fb57e Binary files /dev/null and b/preview/_/img/favicons/favicon-16x16.png differ diff --git a/preview/_/img/favicons/favicon-32x32.png b/preview/_/img/favicons/favicon-32x32.png new file mode 100644 index 0000000..9bd8fe3 Binary files /dev/null and b/preview/_/img/favicons/favicon-32x32.png differ diff --git a/preview/_/img/favicons/favicon.ico b/preview/_/img/favicons/favicon.ico new file mode 100644 index 0000000..b8ea56b Binary files /dev/null and b/preview/_/img/favicons/favicon.ico differ diff --git a/preview/_/img/home-o.svg b/preview/_/img/home-o.svg new file mode 100644 index 0000000..95d193b --- /dev/null +++ b/preview/_/img/home-o.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/home.png b/preview/_/img/home.png new file mode 100644 index 0000000..5584aac Binary files /dev/null and b/preview/_/img/home.png differ diff --git a/preview/_/img/home.svg b/preview/_/img/home.svg new file mode 100644 index 0000000..e63ca19 --- /dev/null +++ b/preview/_/img/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/important.svg b/preview/_/img/important.svg new file mode 100644 index 0000000..f0c7878 --- /dev/null +++ b/preview/_/img/important.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/menu.svg b/preview/_/img/menu.svg new file mode 100644 index 0000000..8b43b2e --- /dev/null +++ b/preview/_/img/menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/next.png b/preview/_/img/next.png new file mode 100644 index 0000000..59800b4 Binary files /dev/null and b/preview/_/img/next.png differ diff --git a/preview/_/img/note.svg b/preview/_/img/note.svg new file mode 100644 index 0000000..7bda42a --- /dev/null +++ b/preview/_/img/note.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/octicons-16.svg b/preview/_/img/octicons-16.svg new file mode 100644 index 0000000..e3b4e20 --- /dev/null +++ b/preview/_/img/octicons-16.svg @@ -0,0 +1 @@ +Octicons v11.2.0 by GitHub - https://primer.style/octicons/ - License: MIT \ No newline at end of file diff --git a/preview/_/img/prev.png b/preview/_/img/prev.png new file mode 100644 index 0000000..d88a40f Binary files /dev/null and b/preview/_/img/prev.png differ diff --git a/preview/_/img/tip.svg b/preview/_/img/tip.svg new file mode 100644 index 0000000..dbdae3e --- /dev/null +++ b/preview/_/img/tip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/img/up.png b/preview/_/img/up.png new file mode 100644 index 0000000..17d9c3e Binary files /dev/null and b/preview/_/img/up.png differ diff --git a/preview/_/img/warning.svg b/preview/_/img/warning.svg new file mode 100644 index 0000000..e82b191 --- /dev/null +++ b/preview/_/img/warning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/_/js/site.js b/preview/_/js/site.js new file mode 100644 index 0000000..f638c12 --- /dev/null +++ b/preview/_/js/site.js @@ -0,0 +1,7 @@ +!function(){"use strict";var t,a,d,i,e,n;function r(e){"dark"===e?d.classList.add(a):d.classList.remove(a)}function c(){var e="dark"==(d.classList.contains(a)?"dark":"light")?"light":"dark";r(e),i.setItem(t,e)}window.self===window.top&&(t="antora-theme",a="dark",d=document.documentElement,i=window.localStorage,r(i.getItem(t)||(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),(n=document.querySelector(".theme-toggle"))&&(n.style.display="inline-flex",n.addEventListener("click",c)),window.matchMedia)&&(n=function(e){i.getItem(t)||r(e.matches?"dark":"light")},(e=window.matchMedia("(prefers-color-scheme: dark)")).addEventListener?e.addEventListener("change",n):e.addListener&&e.addListener(n))}(); +!function(){"use strict";var s,o,r=/^sect(\d)$/,t=document.querySelector(".nav-container"),n=document.querySelector(".nav-toggle"),a=t.querySelector(".nav"),e=t.querySelector(".nav-close"),l=(n.addEventListener("click",function(e){if(n.classList.contains("is-active"))return u(e);v(e);e=document.documentElement;e.classList.add("is-clipped--nav"),n.classList.add("is-active"),t.classList.add("is-active"),e.addEventListener("click",u)}),t.addEventListener("click",v),e.addEventListener("click",u),t.querySelector("[data-panel=menu]"));function i(){var e,t,n=window.location.hash;if(n&&(n.indexOf("%")&&(n=decodeURIComponent(n)),!(e=l.querySelector('.nav-link[href="'+n+'"]')))){n=document.getElementById(n.slice(1));if(n)for(var i=n,c=document.querySelector("article.doc");(i=i.parentNode)&&i!==c;){var a=i.id;if((a=a||(a=r.test(i.className))&&(i.firstElementChild||{}).id)&&(e=l.querySelector('.nav-link[href="#'+a+'"]')))break}}if(e)t=e.parentNode;else{if(!o)return;e=(t=o).querySelector(".nav-link")}t!==s&&(m(l,".is-active, .is-current-path, .is-current-page").forEach(function(e){e.classList.remove("is-active","is-current-path","is-current-page")}),t.classList.add("is-current-page"),d(s=t),p(l,e))}function d(e){for(var t,n=e.parentNode;!(t=n.classList).contains("nav-menu");)"LI"===n.tagName&&t.add("is-active","is-current-path"),n=n.parentNode;e.classList.add("is-active")}function c(){var e,t,n,i;this.classList.toggle("is-active")&&(e=parseFloat(window.getComputedStyle(this).marginTop),t=this.getBoundingClientRect(),n=l.getBoundingClientRect(),0<(i=(t.bottom-n.top-n.height+e).toFixed()))&&(l.scrollTop+=Math.min((t.top-n.top-e).toFixed(),i))}function u(e){v(e);e=document.documentElement;e.classList.remove("is-clipped--nav"),n.classList.remove("is-active"),t.classList.remove("is-active"),e.removeEventListener("click",u)}function v(e){e.stopPropagation()}function p(e,t){var n=e.getBoundingClientRect(),i=n.height,c=window.getComputedStyle(a);"sticky"===c.position&&(i-=n.top-parseFloat(c.top)),e.scrollTop=Math.max(0,.5*(t.getBoundingClientRect().height-i)+t.offsetTop)}function m(e,t){return[].slice.call(e.querySelectorAll(t))}l&&(e=t.querySelector("[data-panel=explore]"),s=l.querySelector(".is-current-page"),(o=s)?(d(s),p(l,s.querySelector(".nav-link"))):l.scrollTop=0,m(l,".nav-item-toggle").forEach(function(e){var t=e.parentElement,e=(e.addEventListener("click",c.bind(t)),function(e,t){e=e.nextElementSibling;return(!e||!t||e[e.matches?"matches":"msMatchesSelector"](t))&&e}(e,".nav-text"));e&&(e.style.cursor="pointer",e.addEventListener("click",c.bind(t)))}),e&&e.querySelector(".context").addEventListener("click",function(){m(a,"[data-panel]").forEach(function(e){e.classList.toggle("is-active")})}),l.addEventListener("mousedown",function(e){1":"")+".sect"+c);r.push("h"+(i+1)+"[id]")}else r.push("h1[id].sect0");n.push(r.join(">"))}m=n.join(","),f=d.parentNode;var a,s=[].slice.call((f||document).querySelectorAll(m));if(!s.length)return e.parentNode.removeChild(e);var l={},u=s.reduce(function(e,t){var o=document.createElement("a"),n=(o.textContent=t.textContent,l[o.href="#"+t.id]=o,document.createElement("li"));return n.dataset.level=parseInt(t.nodeName.slice(1),10)-1,n.appendChild(o),e.appendChild(n),e},document.createElement("ul")),f=e.querySelector(".toc-menu"),m=(f||((f=document.createElement("div")).className="toc-menu"),document.createElement("h3")),e=(m.textContent=e.dataset.title||"Contents",f.appendChild(m),f.appendChild(u),!document.getElementById("toc")&&d.querySelector("h1.page ~ :not(.is-before-toc)"));e&&((m=document.createElement("aside")).className="toc embedded",m.appendChild(f.cloneNode(!0)),e.parentNode.insertBefore(m,e)),window.addEventListener("load",function(){p(),window.addEventListener("scroll",p)})}}function p(){var n,i,t,e=window.pageYOffset,o=1.15*h(document.documentElement,"fontSize"),r=d.offsetTop;e&&window.innerHeight+e+2>=document.documentElement.scrollHeight?(a=Array.isArray(a)?a:Array(a||0),n=[],i=s.length-1,s.forEach(function(e,t){var o="#"+e.id;t===i||e.getBoundingClientRect().top+h(e,"paddingTop")>r?(n.push(o),a.indexOf(o)<0&&l[o].classList.add("is-active")):~a.indexOf(o)&&l[a.shift()].classList.remove("is-active")}),u.scrollTop=u.scrollHeight-u.offsetHeight,a=1r)return!0;t="#"+e.id}),t?t!==a&&(a&&l[a].classList.remove("is-active"),(e=l[t]).classList.add("is-active"),u.scrollHeight>u.offsetHeight&&(u.scrollTop=Math.max(0,e.offsetTop+e.offsetHeight-u.offsetHeight)),a=t):a&&(l[a].classList.remove("is-active"),a=void 0))}function h(e,t){return parseFloat(window.getComputedStyle(e)[t])}}(); +!function(){"use strict";var o=document.querySelector("article.doc"),t=document.querySelector(".toolbar");function i(e){return e&&(~e.indexOf("%")?decodeURIComponent(e):e).slice(1)}function r(e){if(e){if(e.altKey||e.ctrlKey)return;window.location.hash="#"+this.id,e.preventDefault()}window.scrollTo(0,function e(t,n){return o.contains(t)?e(t.offsetParent,t.offsetTop+n):n}(this,0)-t.getBoundingClientRect().bottom)}window.addEventListener("load",function e(t){var n;(n=i(window.location.hash))&&(n=document.getElementById(n))&&(r.bind(n)(),setTimeout(r.bind(n),0)),window.removeEventListener("load",e)}),Array.prototype.slice.call(document.querySelectorAll('a[href^="#"]')).forEach(function(e){var t;(t=i(e.hash))&&(t=document.getElementById(t))&&e.addEventListener("click",r.bind(t))})}(); +!function(){"use strict";var t,e=document.querySelector(".page-versions .version-menu-toggle");e&&(t=document.querySelector(".page-versions"),e.addEventListener("click",function(e){t.classList.toggle("is-active"),e.stopPropagation()}),document.documentElement.addEventListener("click",function(){t.classList.remove("is-active")}))}(); +!function(){"use strict";var t=document.querySelector(".navbar-burger");t&&t.addEventListener("click",function(t){t.stopPropagation(),document.documentElement.classList.toggle("is-clipped--navbar"),this.classList.toggle("is-active");t=document.getElementById(this.dataset.target);{var e;t.classList.toggle("is-active")&&(t.style.maxHeight="",e=window.innerHeight-Math.round(t.getBoundingClientRect().top),parseInt(window.getComputedStyle(t).maxHeight,10)!==e)&&(t.style.maxHeight=e+"px")}}.bind(t))}(); +!function(){"use strict";var o=/^\$ (\S[^\\\n]*(\\\n(?!\$ )[^\\\n]*)*)(?=\n|$)/gm,s=/( ) *\\\n *|\\\n( ?) */g,l=/ +$/gm,e=(document.getElementById("site-script")||{dataset:{}}).dataset,d=null==e.uiRootPath?".":e.uiRootPath,r=e.svgAs,p=window.navigator.clipboard;[].slice.call(document.querySelectorAll(".doc pre.highlight, .doc .literalblock pre")).forEach(function(e){var t,n,a,c;if(e.classList.contains("highlight"))(i=(t=e.querySelector("code")).dataset.lang)&&"console"!==i&&((a=document.createElement("span")).className="source-lang",a.appendChild(document.createTextNode(i)));else{if(!e.innerText.startsWith("$ "))return;var i=e.parentNode.parentNode;i.classList.remove("literalblock"),i.classList.add("listingblock"),e.classList.add("highlightjs","highlight"),(t=document.createElement("code")).className="language-console hljs",t.dataset.lang="console",t.appendChild(e.firstChild),e.appendChild(t)}(i=document.createElement("div")).className="source-toolbox",a&&i.appendChild(a),p&&((n=document.createElement("button")).className="copy-button",n.setAttribute("title","Copy to clipboard"),"svg"===r?((a=document.createElementNS("http://www.w3.org/2000/svg","svg")).setAttribute("class","copy-icon"),(c=document.createElementNS("http://www.w3.org/2000/svg","use")).setAttribute("href",d+"/img/octicons-16.svg#icon-clippy"),a.appendChild(c),n.appendChild(a)):((c=document.createElement("img")).src=d+"/img/octicons-16.svg#view-clippy",c.alt="copy icon",c.className="copy-icon",n.appendChild(c)),(a=document.createElement("span")).className="copy-toast",a.appendChild(document.createTextNode("Copied!")),n.appendChild(a),i.appendChild(n)),e.parentNode.appendChild(i),n&&n.addEventListener("click",function(e){var t=e.innerText.replace(l,"");"console"===e.dataset.lang&&t.startsWith("$ ")&&(t=function(e){var t,n=[];for(;t=o.exec(e);)n.push(t[1].replace(s,"$1$2"));return n.join(" && ")}(t));window.navigator.clipboard.writeText(t).then(function(){this.classList.add("clicked"),this.offsetHeight,this.classList.remove("clicked")}.bind(this),function(){})}.bind(n,t))})}(); \ No newline at end of file diff --git a/preview/_/js/vendor/cpp-highlight.js b/preview/_/js/vendor/cpp-highlight.js new file mode 100644 index 0000000..6af195a --- /dev/null +++ b/preview/_/js/vendor/cpp-highlight.js @@ -0,0 +1 @@ +const CppHighlight=function(){"use strict";const o=new Set(["auto","register","static","extern","mutable","thread_local","const","volatile","constexpr","consteval","constinit","void","bool","char","short","int","long","float","double","signed","unsigned","wchar_t","char8_t","char16_t","char32_t","class","struct","union","enum","typename","typedef","if","else","switch","case","default","for","while","do","break","continue","return","goto","try","catch","throw","noexcept","public","private","protected","virtual","override","final","friend","this","operator","new","delete","template","concept","requires","namespace","using","sizeof","alignof","alignas","decltype","typeid","static_cast","dynamic_cast","const_cast","reinterpret_cast","static_assert","inline","explicit","export","module","import","co_await","co_yield","co_return","true","false","nullptr","NULL"]);function a(e){return e.replace(/&/g,"&").replace(//g,">")}function u(e,t){return`${a(t)}`}function t(i){var r=[];let l=0;for(var n=i.length;l/g,">").replace(/"/g,""").replace(/'/g,"'")}function l(e,...n){const t=Object.create(null);for(const a in e)t[a]=e[a];return n.forEach(function(e){for(const n in e)t[n]=e[n]}),t}const D=e=>!!e.scope,I=(e,{prefix:n})=>{var t;return e.startsWith("language:")?e.replace("language:","language-"):e.includes(".")?[""+n+(t=e.split(".")).shift(),...t.map((e,n)=>""+e+"_".repeat(n+1))].join(" "):""+n+e};class ${constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=n(e)}openNode(e){D(e)&&(e=I(e.scope,{prefix:this.classPrefix}),this.span(e))}closeNode(e){D(e)&&(this.buffer+="")}value(){return this.buffer}span(e){this.buffer+=``}}const F=(e={})=>{var n={children:[]};return Object.assign(n,e),n};class j{constructor(){this.rootNode=F(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){e=F({scope:e});this.add(e),this.stack.push(e)}closeNode(){if(1this._walk(n,e)),n.closeNode(e)),n}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{j._collapse(e)}))}}class U extends j{constructor(e){super(),this.options=e}addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){this.closeNode()}__addSublanguage(e,n){e=e.root;n&&(e.scope="language:"+n),this.add(e)}toHTML(){return new $(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}}function c(e){return e?"string"==typeof e?e:e.source:null}function P(e){return b("(?=",e,")")}function q(e){return b("(?:",e,")*")}function K(e){return b("(?:",e,")?")}function b(...e){return e.map(e=>c(e)).join("")}function m(...e){var n,t="object"==typeof(n=(t=e)[t.length-1])&&n.constructor===Object?(t.splice(t.length-1,1),n):{};return"("+(t.capture?"":"?:")+e.map(e=>c(e)).join("|")+")"}function H(e){return new RegExp(e.toString()+"|").exec("").length-1}const Z=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function t(e,{joinWith:n}){let r=0;return e.map(e=>{var n=r+=1;let t=c(e),a="";for(;0`(${e})`).join(n)}function e(e,n,t={}){return(e=l({scope:"comment",begin:e,end:n,contains:[]},t)).contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}),n=m("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/),e.contains.push({begin:b(/[ ]+/,"(",n,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),e}var a="[a-zA-Z]\\w*",i="[a-zA-Z_]\\w*",r="\\b\\d+(\\.\\d+)?",s="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",o="\\b(0b[01]+)",d={begin:"\\\\[\\s\\S]",relevance:0},g={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[d]},u={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[d]},p=e("//","$"),f=e("/\\*","\\*/"),h=e("#","$"),_=Object.freeze({__proto__:null,APOS_STRING_MODE:g,BACKSLASH_ESCAPE:d,BINARY_NUMBER_MODE:{scope:"number",begin:o,relevance:0},BINARY_NUMBER_RE:o,COMMENT:e,C_BLOCK_COMMENT_MODE:f,C_LINE_COMMENT_MODE:p,C_NUMBER_MODE:{scope:"number",begin:s,relevance:0},C_NUMBER_RE:s,END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})},HASH_COMMENT_MODE:h,IDENT_RE:a,MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+i,relevance:0},NUMBER_MODE:{scope:"number",begin:r,relevance:0},NUMBER_RE:r,PHRASAL_WORDS_MODE:{begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},QUOTE_STRING_MODE:u,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[d,{begin:/\[/,end:/\]/,relevance:0,contains:[d]}]},RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{var n=/^#![ ]*\//;return e.binary&&(e.begin=b(n,/.*\b/,e.binary,/\b.*/)),l({scope:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},TITLE_MODE:{scope:"title",begin:a,relevance:0},UNDERSCORE_IDENT_RE:i,UNDERSCORE_TITLE_MODE:{scope:"title",begin:i,relevance:0}});function G(e,n){"."===e.input[e.index-1]&&n.ignoreMatch()}function W(e,n){void 0!==e.className&&(e.scope=e.className,delete e.className)}function Q(e,n){n&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=G,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,void 0===e.relevance)&&(e.relevance=0)}function X(e,n){Array.isArray(e.illegal)&&(e.illegal=m(...e.illegal))}function V(e,n){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function J(e,n){void 0===e.relevance&&(e.relevance=1)}const Y=(n,e)=>{if(n.beforeMatch){if(n.starts)throw new Error("beforeMatch cannot be used with starts");var t=Object.assign({},n);Object.keys(n).forEach(e=>{delete n[e]}),n.keywords=t.keywords,n.begin=b(t.beforeMatch,P(t.begin)),n.starts={relevance:0,contains:[Object.assign(t,{endsParent:!0})]},n.relevance=0,delete t.beforeMatch}},ee=["of","and","for","in","not","or","if","then","parent","list","value"],ne="keyword";function te(n,t,e=ne){const a=Object.create(null);return"string"==typeof n?i(e,n.split(" ")):Array.isArray(n)?i(e,n):Object.keys(n).forEach(function(e){Object.assign(a,te(n[e],t,e))}),a;function i(n,e){(e=t?e.map(e=>e.toLowerCase()):e).forEach(function(e){e=e.split("|");a[e[0]]=[n,function(e,n){if(n)return Number(n);return function(e){return ee.includes(e.toLowerCase())}(e)?0:1}(e[0],e[1])]})}}const ae={},B=e=>{console.error(e)},ie=(e,...n)=>{console.log("WARN: "+e,...n)},y=(e,n)=>{ae[e+"/"+n]||(console.log(`Deprecated as of ${e}. `+n),ae[e+"/"+n]=!0)},v=new Error;function re(e,n,{key:t}){let a=0;var i=e[t],r={},s={};for(let e=1;e<=n.length;e++)s[e+a]=i[e],r[e+a]=!0,a+=H(n[e-1]);e[t]=s,e[t]._emit=r,e[t]._multi=!0}function se(e){(n=e).scope&&"object"==typeof n.scope&&null!==n.scope&&(n.beginScope=n.scope,delete n.scope),"string"==typeof e.beginScope&&(e.beginScope={_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope});var n=e;if(Array.isArray(n.begin)){if(n.skip||n.excludeBegin||n.returnBegin)throw B("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),v;if("object"!=typeof n.beginScope||null===n.beginScope)throw B("beginScope must be object"),v;re(n,n.begin,{key:"beginScope"}),n.begin=t(n.begin,{joinWith:""})}n=e;if(Array.isArray(n.end)){if(n.skip||n.excludeEnd||n.returnEnd)throw B("skip, excludeEnd, returnEnd not compatible with endScope: {}"),v;if("object"!=typeof n.endScope||null===n.endScope)throw B("endScope must be object"),v;re(n,n.end,{key:"endScope"}),n.end=t(n.end,{joinWith:""})}}function oe(r){function s(e,n){return new RegExp(c(e),"m"+(r.case_insensitive?"i":"")+(r.unicodeRegex?"u":"")+(n?"g":""))}class n{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=H(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);var e=this.regexes.map(e=>e[1]);this.matcherRe=s(t(e,{joinWith:"|"}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;var n,t,e=this.matcherRe.exec(e);return e?(n=e.findIndex((e,n)=>0t.addRule(e,n)),t.compile(),this.multiRegexes[e]=t}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){var n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;let t=n.exec(e);return!this.resumingScanAtSamePosition()||t&&t.index===this.lastIndex||((n=this.getMatcher(0)).lastIndex=this.lastIndex+1,t=n.exec(e)),t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count)&&this.considerAll(),t}}if(r.compilerExtensions||(r.compilerExtensions=[]),r.contains&&r.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return r.classNameAliases=l(r.classNameAliases||{}),function n(t,a){const i=t;if(!t.isCompiled){[W,V,se,Y].forEach(e=>e(t,a)),r.compilerExtensions.forEach(e=>e(t,a)),t.__beforeBegin=null,[Q,X,J].forEach(e=>e(t,a)),t.isCompiled=!0;let e=null;"object"==typeof t.keywords&&t.keywords.$pattern&&(t.keywords=Object.assign({},t.keywords),e=t.keywords.$pattern,delete t.keywords.$pattern),e=e||/\w+/,t.keywords&&(t.keywords=te(t.keywords,r.case_insensitive)),i.keywordPatternRe=s(e,!0),a&&(t.begin||(t.begin=/\B|\b/),i.beginRe=s(i.begin),t.end||t.endsWithParent||(t.end=/\B|\b/),t.end&&(i.endRe=s(i.end)),i.terminatorEnd=c(i.end)||"",t.endsWithParent)&&a.terminatorEnd&&(i.terminatorEnd+=(t.end?"|":"")+a.terminatorEnd),t.illegal&&(i.illegalRe=s(t.illegal)),t.contains||(t.contains=[]),t.contains=[].concat(...t.contains.map(function(e){var n="self"===e?t:e;return n.variants&&!n.cachedVariants&&(n.cachedVariants=n.variants.map(function(e){return l(n,{variants:null},e)})),n.cachedVariants||(function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(n)?l(n,{starts:n.starts?l(n.starts):null}):Object.isFrozen(n)?l(n):n)})),t.contains.forEach(function(e){n(e,i)}),t.starts&&n(t.starts,a),i.matcher=function(e){const n=new o;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminatorEnd&&n.addRule(e.terminatorEnd,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(i)}return i}(r)}class le extends Error{constructor(e,n){super(e),this.name="HTMLInjectionError",this.html=n}}function ce(a){const A=Object.create(null),s=Object.create(null),i=[];let S=!0;const C="Could not find the language '{}', did you forget to load/include a language module?",r={disableAutodetect:!0,name:"Plain text",contains:[]};let T={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:U};function o(e){return T.noHighlightRe.test(e)}function l(e,n,t){let a="",i="";"object"==typeof n?(a=e,t=n.ignoreIllegals,i=n.language):(y("10.7.0","highlight(lang, code, ...args) has been deprecated."),y("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),i=e,a=n),void 0===t&&(t=!0);e={code:a,language:i},g("before:highlight",e),n=e.result||R(e.language,e.code,t);return n.code=e.code,g("after:highlight",n),n}function R(a,i,r,e){const s=Object.create(null);function o(){if(h.keywords){let e=0,n=(h.keywordPatternRe.lastIndex=0,h.keywordPatternRe.exec(E)),t="";for(;n;){t+=E.substring(e,n.index);var a,i=p.case_insensitive?n[0].toLowerCase():n[0],r=h.keywords[i];!r||([r,a]=r,y.addText(t),t="",s[i]=(s[i]||0)+1,s[i]<=7&&(w+=a),r.startsWith("_"))?t+=n[0]:(i=p.classNameAliases[r]||r,c(n[0],i)),e=h.keywordPatternRe.lastIndex,n=h.keywordPatternRe.exec(E)}t+=E.substring(e),y.addText(t)}else y.addText(E)}function l(){(null!=h.subLanguage?function(){if(""!==E){let e=null;if("string"==typeof h.subLanguage){if(!A[h.subLanguage])return y.addText(E);e=R(h.subLanguage,E,!0,_[h.subLanguage]),_[h.subLanguage]=e._top}else e=D(E,h.subLanguage.length?h.subLanguage:null);0")+'"')).mode=h,e;if("end"===n.type){e=b(n);if(e!==ge)return e}if("illegal"===n.type&&""===t)return E+="\n",1;if(1e53*n.index)throw new Error("potential infinite loop, way more iterations than matches");return E+=t,t.length}const p=I(a);if(!p)throw B(C.replace("{}",a)),new Error('Unknown language: "'+a+'"');var t=oe(p);let f="",h=e||t;const _={},y=new T.__emitter(T);var v=[];for(let e=h;e!==p;e=e.parent)e.scope&&v.unshift(e.scope);v.forEach(e=>y.openNode(e));let E="",w=0,k=0,N=0,x=!1;try{if(p.__emitTokens)p.__emitTokens(i,y);else{for(h.matcher.considerAll();;){N++,x?x=!1:h.matcher.considerAll(),h.matcher.lastIndex=k;var O=h.matcher.exec(i);if(!O)break;var M=n(i.substring(k,O.index),O);k=O.index+M}n(i.substring(k))}return y.finalize(),f=y.toHTML(),{language:a,value:f,relevance:w,illegal:!1,_emitter:y,_top:h}}catch(e){if(e.message&&e.message.includes("Illegal"))return{language:a,value:z(i),illegal:!0,relevance:0,_illegalBy:{message:e.message,index:k,context:i.slice(k-100,k+100),mode:e.mode,resultSoFar:f},_emitter:y};if(S)return{language:a,value:z(i),illegal:!1,relevance:0,errorRaised:e,_emitter:y,_top:h};throw e}}function D(n,e){e=e||T.languages||Object.keys(A);t=n,(a={value:z(t),illegal:!1,relevance:0,_top:r,_emitter:new T.__emitter(T)})._emitter.addText(t);var t=a,a=e.filter(I).filter(d).map(e=>R(e,n,!1)),e=(a.unshift(t),a.sort((e,n)=>{if(e.relevance!==n.relevance)return n.relevance-e.relevance;if(e.language&&n.language){if(I(e.language).supersetOf===n.language)return 1;if(I(n.language).supersetOf===e.language)return-1}return 0})),[t,a]=e,e=t;return e.secondBest=a,e}function n(e){t=(n=e).className+" ",t+=n.parentNode?n.parentNode.className:"";var n=(r=T.languageDetectRe.exec(t))?((i=I(r[1]))||(ie(C.replace("{}",r[1])),ie("Falling back to no-highlight mode for this block.",n)),i?r[1]:"no-highlight"):t.split(/\s+/).find(e=>o(e)||I(e));if(!o(n))if(g("before:highlightElement",{el:e,language:n}),e.dataset.highlighted)console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e);else{if(0{s[e.toLowerCase()]=n})}function d(e){e=I(e);return e&&!e.disableAutodetect}function g(e,n){const t=e;i.forEach(function(e){e[t]&&e[t](n)})}Object.assign(a,{highlight:l,highlightAuto:D,highlightAll:t,highlightElement:n,highlightBlock:function(e){return y("10.7.0","highlightBlock will be removed entirely in v12.0"),y("10.7.0","Please use highlightElement now."),n(e)},configure:function(e){T=de(T,e)},initHighlighting:()=>{t(),y("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")},initHighlightingOnLoad:function(){t(),y("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")},registerLanguage:function(n,e){let t=null;try{t=e(a)}catch(e){if(B("Language definition for '{}' could not be registered.".replace("{}",n)),!S)throw e;B(e),t=r}t.name||(t.name=n),(A[n]=t).rawDefinition=e.bind(null,a),t.aliases&&c(t.aliases,{languageName:n})},unregisterLanguage:function(e){delete A[e];for(const n of Object.keys(s))s[n]===e&&delete s[n]},listLanguages:function(){return Object.keys(A)},getLanguage:I,registerAliases:c,autoDetection:d,inherit:de,addPlugin:function(e){var n;(n=e)["before:highlightBlock"]&&!n["before:highlightElement"]&&(n["before:highlightElement"]=e=>{n["before:highlightBlock"](Object.assign({block:e.el},e))}),n["after:highlightBlock"]&&!n["after:highlightElement"]&&(n["after:highlightElement"]=e=>{n["after:highlightBlock"](Object.assign({block:e.el},e))}),i.push(e)},removePlugin:function(e){-1!==(e=i.indexOf(e))&&i.splice(e,1)}}),a.debugMode=function(){S=!1},a.safeMode=function(){S=!0},a.versionString="11.11.1",a.regex={concat:b,lookahead:P,either:m,optional:K,anyNumberOfTimes:q};for(const u in _)"object"==typeof _[u]&&!function t(a){a instanceof Map?a.clear=a.delete=a.set=function(){throw new Error("map is read-only")}:a instanceof Set&&(a.add=a.clear=a.delete=function(){throw new Error("set is read-only")}),Object.freeze(a),Object.getOwnPropertyNames(a).forEach(e=>{var n=typeof(e=a[e]);"object"!=n&&"function"!=n||Object.isFrozen(e)||t(e)})}(_[u]);return Object.assign(a,_),a}const z=n,de=l,ge=Symbol("nomatch");g=ce({}),g.newInstance=()=>ce({}),o=g;(g.HighlightJS=g).default=g;function ue(e){var n=e.regex,t=n.concat(/[\p{L}_]/u,n.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),a={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},i={begin:/\s/,contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},r=e.inherit(i,{begin:/\(/,end:/\)/}),s=e.inherit(e.APOS_STRING_MODE,{className:"string"}),o=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),l={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,unicodeRegex:!0,contains:[{className:"meta",begin://,relevance:10,contains:[i,o,s,r,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[i,r,o,s]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},a,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/,relevance:10,contains:[o]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[l],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[l],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:n.concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:t,relevance:0,starts:l}]},{className:"tag",begin:n.concat(/<\//,n.lookahead(n.concat(t,/>/))),contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}function be(e){var n=e.regex,t={},a={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]},n=(Object.assign(t,{className:"variable",variants:[{begin:n.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},a]}),{className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]}),a=e.inherit(e.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),i={begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},r={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,t,n]},n=(n.contains.push(r),{begin:/\$?\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t]}),s=e.SHEBANG({binary:`(${["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"].join("|")})`,relevance:10}),o={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/,keyword:["if","then","else","elif","fi","time","for","while","until","in","do","done","case","esac","coproc","function","select"],literal:["true","false"],built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","sudo","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"]},contains:[s,e.SHEBANG(),o,n,a,i,{match:/(\/[a-z._-]+)+/},r,{match:/\\"/},{className:"string",begin:/'/,end:/'/},{match:/\\'/},t]}}function me(e){var n=e.regex,t=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]}),a="decltype\\(auto\\)",i="[a-zA-Z_]\\w*::",r="("+a+"|"+n.optional(i)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",s={className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{match:/\batomic_[a-z]{3,6}\b/}]},o={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},l={className:"number",variants:[{match:/\b(0b[01']+)/},{match:/(-?)\b([\d']+(\.[\d']*)?|\.[\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)/},{match:/(-?)\b(0[xX][a-fA-F0-9]+(?:'[a-fA-F0-9]+)*(?:\.[a-fA-F0-9]*(?:'[a-fA-F0-9]*)*)?(?:[pP][-+]?[0-9]+)?(l|L)?(u|U)?)/},{match:/(-?)\b\d+(?:'\d+)*(?:\.\d*(?:'\d*)*)?(?:[eE][-+]?\d+)?/}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef elifdef elifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(o,{className:"string"}),{className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},d={className:"title",begin:n.optional(i)+e.IDENT_RE,relevance:0},n=n.optional(i)+e.IDENT_RE+"\\s*\\(",i={keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","typeof","typeof_unqual","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"],type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_BitInt","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal96","_Decimal128","_Decimal64x","_Decimal128x","_Float16","_Float32","_Float64","_Float128","_Float32x","_Float64x","_Float128x","const","static","constexpr","complex","bool","imaginary"],literal:"true false NULL",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr"},g=[c,s,t,e.C_BLOCK_COMMENT_MODE,l,o],u={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:i,contains:g.concat([{begin:/\(/,end:/\)/,keywords:i,contains:g.concat(["self"]),relevance:0}]),relevance:0},r={begin:"("+r+"[\\*&\\s]+)+"+n,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:i,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:a,keywords:i,relevance:0},{begin:n,returnBegin:!0,contains:[e.inherit(d,{className:"title.function"})],relevance:0},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,o,l,s,{begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,o,l,s]}]},s,t,e.C_BLOCK_COMMENT_MODE,c]};return{name:"C",aliases:["h"],keywords:i,disableAutodetect:!0,illegal:"=]/,contains:[{beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:c,strings:o,keywords:i}}}function pe(e){var n=e.regex,t=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]}),a="decltype\\(auto\\)",i="[a-zA-Z_]\\w*::",r="(?!struct)("+a+"|"+n.optional(i)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",s={className:"type",begin:"\\b[a-z\\d_]*_t\\b"},o={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},l={className:"number",variants:[{begin:"[+-]?(?:(?:[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?|\\.[0-9](?:'?[0-9])*)(?:[Ee][+-]?[0-9](?:'?[0-9])*)?|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*|0[Xx](?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)[Pp][+-]?[0-9](?:'?[0-9])*)(?:[Ff](?:16|32|64|128)?|(BF|bf)16|[Ll]|)"},{begin:"[+-]?\\b(?:0[Bb][01](?:'?[01])*|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*|0(?:'?[0-7])*|[1-9](?:'?[0-9])*)(?:[Uu](?:LL?|ll?)|[Uu][Zz]?|(?:LL?|ll?)[Uu]?|[Zz][Uu]|)"}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(o,{className:"string"}),{className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},d={className:"title",begin:n.optional(i)+e.IDENT_RE,relevance:0},i=n.optional(i)+e.IDENT_RE+"\\s*\\(",g={type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"],keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"],literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"],_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","flat_map","flat_set","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"]},u=[n={className:"function.dispatch",relevance:0,keywords:{_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"]},begin:n.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!switch)/,/(?!while)/,e.IDENT_RE,n.lookahead(/(<[^<>]+>|)\s*\(/))},c,s,t,e.C_BLOCK_COMMENT_MODE,l,o],b={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:g,contains:u.concat([{begin:/\(/,end:/\)/,keywords:g,contains:u.concat(["self"]),relevance:0}]),relevance:0},r={className:"function",begin:"("+r+"[\\*&\\s]+)+"+i,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:g,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:a,keywords:g,relevance:0},{begin:i,returnBegin:!0,contains:[d],relevance:0},{begin:/::/,relevance:0},{begin:/:/,endsWithParent:!0,contains:[o,l]},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,o,l,s,{begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,o,l,s]}]},s,t,e.C_BLOCK_COMMENT_MODE,c]};return{name:"C++",aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:g,illegal:"",keywords:g,contains:["self",s]},{begin:e.IDENT_RE+"::",keywords:g},{match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/],className:{1:"keyword",3:"title.class"}}])}}function fe(e){var n={keyword:["abstract","as","base","break","case","catch","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","scoped","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","args","async","await","by","descending","dynamic","equals","file","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","record","remove","required","scoped","select","set","unmanaged","value|0","var","when","where","with","yield"]),built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"],literal:["default","false","null","true"]},t=e.inherit(e.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},i={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},r=e.inherit(i,{illegal:/\n/}),s={className:"subst",begin:/\{/,end:/\}/,keywords:n},o=e.inherit(s,{illegal:/\n/}),l={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/},e.BACKSLASH_ESCAPE,o]},c={className:"string",begin:/\$@"/,end:'"',contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},s]},d=e.inherit(c,{illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},o]}),s=(s.contains=[c,l,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],o.contains=[d,l,r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{illegal:/\n/})],{variants:[{className:"string",begin:/"""("*)(?!")(.|\n)*?"""\1/,relevance:1},c,l,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]}),o={begin:"<",end:">",contains:[{beginKeywords:"in out"},t]},d=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",r={begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:""}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{keyword:"if else elif endif define undef warning error line region endregion pragma checksum"}},s,a,{beginKeywords:"class interface",relevance:0,end:/[{;=]/,illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"},t,o,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,contains:[t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,contains:[t,o,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+d+"\\s+)+"+e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{beginKeywords:["public","private","protected","static","internal","protected","abstract","async","extern","override","unsafe","virtual","new","sealed","partial"].join(" "),relevance:0},{begin:e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,contains:[e.TITLE_MODE,o],relevance:0},{match:/\(\)/},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,contains:[s,a,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},r]}}const he=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],_e=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),ye=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),ve=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),Ee=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-align","box-decoration-break","box-direction","box-flex","box-flex-group","box-lines","box-ordinal-group","box-orient","box-pack","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","contain-intrinsic-block-size","contain-intrinsic-height","contain-intrinsic-inline-size","contain-intrinsic-size","contain-intrinsic-width","container","container-name","container-type","content","content-visibility","counter-increment","counter-reset","counter-set","cue","cue-after","cue-before","cursor","cx","cy","direction","display","dominant-baseline","empty-cells","enable-background","field-sizing","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flood-color","flood-opacity","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-palette","font-size","font-size-adjust","font-smooth","font-smoothing","font-stretch","font-style","font-synthesis","font-synthesis-position","font-synthesis-small-caps","font-synthesis-style","font-synthesis-weight","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-emoji","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","forced-color-adjust","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphenate-character","hyphenate-limit-chars","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","initial-letter","initial-letter-align","inline-size","inset","inset-area","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","kerning","left","letter-spacing","lighting-color","line-break","line-height","line-height-step","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","margin-trim","marker","marker-end","marker-mid","marker-start","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","masonry-auto-flow","math-depth","math-shift","math-style","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-anchor","overflow-block","overflow-clip-margin","overflow-inline","overflow-wrap","overflow-x","overflow-y","overlay","overscroll-behavior","overscroll-behavior-block","overscroll-behavior-inline","overscroll-behavior-x","overscroll-behavior-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","paint-order","pause","pause-after","pause-before","perspective","perspective-origin","place-content","place-items","place-self","pointer-events","position","position-anchor","position-visibility","print-color-adjust","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","ruby-align","ruby-position","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scroll-timeline","scroll-timeline-axis","scroll-timeline-name","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","speak","speak-as","src","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","tab-size","table-layout","text-align","text-align-all","text-align-last","text-anchor","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-size-adjust","text-transform","text-underline-offset","text-underline-position","text-wrap","text-wrap-mode","text-wrap-style","timeline-scope","top","touch-action","transform","transform-box","transform-origin","transform-style","transition","transition-behavior","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","user-modify","user-select","vector-effect","vertical-align","view-timeline","view-timeline-axis","view-timeline-inset","view-timeline-name","view-transition-name","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","white-space-collapse","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index","zoom"].sort().reverse();function we(e){var n=e.regex,t={IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/}},e=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:"CSS",case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"},classNameAliases:{keyframePosition:"selector-tag"},contains:[t.BLOCK_COMMENT,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/},t.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},t.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{begin:":("+ye.join("|")+")"},{begin:":(:)?("+ve.join("|")+")"}]},t.CSS_VARIABLE,{className:"attribute",begin:"\\b("+Ee.join("|")+")\\b"},{begin:/:/,end:/[;}{]/,contains:[t.BLOCK_COMMENT,t.HEXCOLOR,t.IMPORTANT,t.CSS_NUMBER_MODE,...e,{begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri"},contains:[...e,{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}]},t.FUNCTION_DISPATCH]},{begin:n.lookahead(/@/),end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:_e.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute"},...e,t.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"\\b("+he.join("|")+")\\b"}]}}function ke(e){var n={begin:/<\/?[A-Za-z_]/,end:">",subLanguage:"xml",relevance:0},t={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,relevance:2},{begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/),relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}]},a={className:"strong",contains:[],variants:[{begin:/_{2}(?!\s)/,end:/_{2}/},{begin:/\*{2}(?!\s)/,end:/\*{2}/}]},i={className:"emphasis",contains:[],variants:[{begin:/\*(?![*\s])/,end:/\*/},{begin:/_(?![_\s])/,end:/_/,relevance:0}]},r=e.inherit(a,{contains:[]}),e=e.inherit(i,{contains:[]});a.contains.push(e),i.contains.push(r);let s=[n,t];return[a,i,r,e].forEach(e=>{e.contains=e.contains.concat(s)}),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:s=s.concat(a,i)},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:s}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},a,i,{className:"quote",begin:"^>\\s+",contains:s,end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},t,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]},{scope:"literal",match:/&([a-zA-Z0-9]+|#[0-9]{1,7}|#[Xx][0-9a-fA-F]{1,6});/}]}}function Ne(e){return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,match:(e=e.regex).either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)},{className:"comment",variants:[{begin:e.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,end:/$/}]}}function xe(e){var n=e.regex,t="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",a=n.either(/\b([A-Z]+[a-z0-9]+)+/,/\b([A-Z]+[a-z0-9]+)+[A-Z]+/),i=n.concat(a,/(::\w+)*/),r={"variable.constant":["__FILE__","__LINE__","__ENCODING__"],"variable.language":["self","super"],keyword:["alias","and","begin","BEGIN","break","case","class","defined","do","else","elsif","end","END","ensure","for","if","in","module","next","not","or","redo","require","rescue","retry","return","then","undef","unless","until","when","while","yield","include","extend","prepend","public","private","protected","raise","throw"],built_in:["proc","lambda","attr_accessor","attr_reader","attr_writer","define_method","private_constant","module_function"],literal:["true","false","nil"]},s={className:"doctag",begin:"@[A-Za-z]+"},o={begin:"#<",end:">"},s=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^=begin","^=end",{contains:[s],relevance:10}),e.COMMENT("^__END__",e.MATCH_NOTHING_RE)],l={className:"subst",begin:/#\{/,end:/\}/,keywords:r},n={className:"string",contains:[e.BACKSLASH_ESCAPE,l],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{begin:n.concat(/<<[-~]?'?/,n.lookahead(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)),contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,l]})]}]},c={className:"number",relevance:0,variants:[{begin:`\\b([1-9](_?[0-9])*|0)(\\.(${c="[0-9](_?[0-9])*"}))?([eE][+-]?(${c})|r)?i?\\b`},{begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{begin:"\\b0(_?[0-7])+r?i?\\b"}]},d={variants:[{match:/\(\)/},{className:"params",begin:/\(/,end:/(?=\))/,excludeBegin:!0,endsParent:!0,keywords:r}]},i=[n,{variants:[{match:[/class\s+/,i,/\s+<\s+/,i]},{match:[/\b(class|module)\s+/,i]}],scope:{2:"title.class",4:"title.class.inherited"},keywords:r},{match:[/(include|extend)\s+/,i],scope:{2:"title.class"},keywords:r},{relevance:0,match:[i,/\.new[. (]/],scope:{1:"title.class"}},{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},{relevance:0,match:a,scope:"title.class"},{match:[/def/,/\s+/,t],scope:{1:"keyword",3:"title.function"},contains:[d]},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[n,{begin:t}],relevance:0},c,{className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{className:"params",begin:/\|(?!=)/,end:/\|/,excludeBegin:!0,excludeEnd:!0,relevance:0,keywords:r},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,l],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(o,s),relevance:0}].concat(o,s),a=(l.contains=i,[{begin:/^\s*=>/,starts:{end:"$",contains:d.contains=i}},{className:"meta.prompt",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+[>*]|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])",starts:{end:"$",keywords:r,contains:i}}]);return s.unshift(o),{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:r,illegal:/\/\*/,contains:[e.SHEBANG({binary:"ruby"})].concat(a).concat(s).concat(i)}}function Oe(e){var n={keyword:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var"],type:["bool","byte","complex64","complex128","error","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"],literal:["true","false","iota","nil"],built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"]};return{name:"Go",aliases:["golang"],keywords:n,illegal:"n(t,a,i-1))}("(?:<"+t+"~~~(?:\\s*,\\s*"+t+"~~~)*>)?",/~~~/g,2),i={keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do","sealed","yield","permits","goto","when"],literal:["false","true","null"],type:["char","boolean","long","float","int","byte","short","double"],built_in:["super","this"]},r={className:"meta",begin:"@"+t,contains:[{begin:/\(/,end:/\)/,contains:["self"]}]},s={className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0};return{name:"Java",aliases:["jsp"],keywords:i,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{begin:/import java\.[a-z]+\./,keywords:"import",relevance:2},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{begin:/"""/,end:/"""/,className:"string",contains:[e.BACKSLASH_ESCAPE]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,t],className:{1:"keyword",3:"title.class"}},{match:/non-sealed/,scope:"keyword"},{begin:[n.concat(/(?!else)/,t),/\s+/,t,/\s+/,/=(?!=)/],className:{1:"type",3:"variable",5:"operator"}},{begin:[/record/,/\s+/,t],className:{1:"keyword",3:"title.class"},contains:[s,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"new throw return else",relevance:0},{begin:["(?:"+a+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{2:"title.function"},keywords:i,contains:[{className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,Se,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},Se,r]}}const Te="[A-Za-z$_][0-9A-Za-z$_]*",Re=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends","using"],De=["true","false","null","undefined","NaN","Infinity"],Ie=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],Le=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],Be=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],ze=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],$e=[].concat(Be,Ie,Le);function Fe(e){const n=e.regex;var t=Te;const a="<>",i="",r=/<[A-Za-z0-9\\._:-]+/,s=/\/[A-Za-z0-9\\._:-]+>|\/>/,o=(e,n)=>{var t,a,i=e[0].length+e.index,r=e.input[i];("<"===r||","===r||(">"===r&&([r,t]=[e,{after:i}["after"]],a="e+"\\s*\\("),n.concat("(?!",v.join("|"),")")),t,n.lookahead(/\s*\(/)),className:"title.function",relevance:0},E={begin:n.concat(/\./,n.lookahead(n.concat(t,/(?![0-9A-Za-z$_(])/))),end:t,excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},w={match:[/get|set/,/\s+/,t,/(?=\()/],className:{1:"keyword",3:"title.function"},contains:[{begin:/\(\)/},f]},k="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+e.UNDERSCORE_IDENT_RE+")\\s*=>",N={match:[/const|var|let/,/\s+/,t,/\s*/,/=\s*/,/(async\s*)?/,n.lookahead(k)],keywords:"async",className:{1:"keyword",3:"title.function"},contains:[f]};return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:l,exports:{PARAMS_CONTAINS:d,CLASS_REFERENCE:_},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:"shebang",binary:"node",relevance:5}),{label:"use_strict",className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,g,u,b,m,p,{match:/\$\d+/},c,_,{scope:"attr",match:t+n.lookahead(":"),relevance:0},N,{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",relevance:0,contains:[p,e.REGEXP_MODE,{className:"function",begin:k,returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:l,contains:d}]}]},{begin:/,/,relevance:0},{match:/\s+/,relevance:0},{variants:[{begin:a,end:i},{match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:r,"on:begin":o,end:s}],subLanguage:"xml",contains:[{begin:r,end:s,skip:!0,contains:["self"]}]}]},y,{beginKeywords:"while if switch catch for"},{begin:"\\b(?!function)"+e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,label:"func.def",contains:[f,e.inherit(e.TITLE_MODE,{begin:t,className:"title.function"})]},{match:/\.\.\./,relevance:0},E,{match:"\\$"+t,relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},contains:[f]},v,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},h,w,{match:/\$[(.]/}]}}function je(e){var n=["true","false","null"],t={scope:"literal",beginKeywords:n.join(" ")};return{name:"JSON",aliases:["jsonc"],keywords:{literal:n},contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,t,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}}var h="[0-9](_*[0-9])*",r=`\\.(${h})`,u="[0-9a-fA-F](_*[0-9a-fA-F])*",Ue={className:"number",variants:[{begin:`(\\b(${h})((${r})|\\.)?|(${r}))`+`[eE][+-]?(${h})[fFdD]?\\b`},{begin:`\\b(${h})((${r})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${r})[fFdD]?\\b`},{begin:`\\b(${h})[fFdD]\\b`},{begin:`\\b0[xX]((${u})\\.?|(${u})?\\.(${u}))`+`[pP][+-]?(${h})[fFdD]?\\b`},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${u})[lL]?\\b`},{begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}],relevance:0};function Pe(e){var n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},t={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},a={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},i={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[i={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},a]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,i,a]}]},a=(a.contains.push(i),{className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"}),r={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(i,{className:"string"}),"self"]}]},s=Ue,o=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),l={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},c=l;return c.variants[1].contains=[l],l.variants[1].contains=[c],{name:"Kotlin",aliases:["kt","kts"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,o,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},t,a,r,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[l,e.C_LINE_COMMENT_MODE,o],relevance:0},e.C_LINE_COMMENT_MODE,o,a,r,i,e.C_NUMBER_MODE]},o]},{begin:[/class|interface|trait/,/\s+/,e.UNDERSCORE_IDENT_RE],beginScope:{3:"title.class"},keywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,){\s]|$/,excludeBegin:!0,returnEnd:!0},a,r]},i,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},s]}}const qe=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],Ke=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),He=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),Ze=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),Ge=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-align","box-decoration-break","box-direction","box-flex","box-flex-group","box-lines","box-ordinal-group","box-orient","box-pack","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","contain-intrinsic-block-size","contain-intrinsic-height","contain-intrinsic-inline-size","contain-intrinsic-size","contain-intrinsic-width","container","container-name","container-type","content","content-visibility","counter-increment","counter-reset","counter-set","cue","cue-after","cue-before","cursor","cx","cy","direction","display","dominant-baseline","empty-cells","enable-background","field-sizing","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flood-color","flood-opacity","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-palette","font-size","font-size-adjust","font-smooth","font-smoothing","font-stretch","font-style","font-synthesis","font-synthesis-position","font-synthesis-small-caps","font-synthesis-style","font-synthesis-weight","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-emoji","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","forced-color-adjust","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphenate-character","hyphenate-limit-chars","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","initial-letter","initial-letter-align","inline-size","inset","inset-area","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","kerning","left","letter-spacing","lighting-color","line-break","line-height","line-height-step","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","margin-trim","marker","marker-end","marker-mid","marker-start","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","masonry-auto-flow","math-depth","math-shift","math-style","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-anchor","overflow-block","overflow-clip-margin","overflow-inline","overflow-wrap","overflow-x","overflow-y","overlay","overscroll-behavior","overscroll-behavior-block","overscroll-behavior-inline","overscroll-behavior-x","overscroll-behavior-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","paint-order","pause","pause-after","pause-before","perspective","perspective-origin","place-content","place-items","place-self","pointer-events","position","position-anchor","position-visibility","print-color-adjust","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","ruby-align","ruby-position","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scroll-timeline","scroll-timeline-axis","scroll-timeline-name","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","speak","speak-as","src","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","tab-size","table-layout","text-align","text-align-all","text-align-last","text-anchor","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-size-adjust","text-transform","text-underline-offset","text-underline-position","text-wrap","text-wrap-mode","text-wrap-style","timeline-scope","top","touch-action","transform","transform-box","transform-origin","transform-style","transition","transition-behavior","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","user-modify","user-select","vector-effect","vertical-align","view-timeline","view-timeline-axis","view-timeline-inset","view-timeline-name","view-transition-name","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","white-space-collapse","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index","zoom"].sort().reverse(),We=He.concat(Ze).sort().reverse();function Qe(e){function n(e){return{className:"string",begin:"~?"+e+".*?"+e}}function t(e,n,t){return{className:e,begin:n,relevance:t}}var a={IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/}},i=We,r="[\\w-]+",s="("+r+"|@\\{"+r+"\\})",o=[],l=[],c={$pattern:/[a-z-]+/,keyword:"and or not only",attribute:Ke.join(" ")},d=(l.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n("'"),n('"'),a.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},a.HEXCOLOR,{begin:"\\(",end:"\\)",contains:l,keywords:c,relevance:0},t("variable","@@?"+r,10),t("variable","@\\{"+r+"\\}"),t("built_in","~?`[^`]*?`"),{className:"attribute",begin:r+"\\s*:",end:":",returnBegin:!0,excludeEnd:!0},a.IMPORTANT,{beginKeywords:"and not"},a.FUNCTION_DISPATCH),l.concat({begin:/\{/,end:/\}/,contains:o})),g={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(l)},u={begin:s+"\\s*:",returnBegin:!0,end:/[;}]/,relevance:0,contains:[{begin:/-(webkit|moz|ms|o)-/},a.CSS_VARIABLE,{className:"attribute",begin:"\\b("+Ge.join("|")+")\\b",end:/(?=:)/,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:l}}]},c={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",keywords:c,returnEnd:!0,contains:l,relevance:0}},l={className:"variable",variants:[{begin:"@"+r+"\\s*:",relevance:15},{begin:"@"+r}],starts:{end:"[;}]",returnEnd:!0,contains:d}},s={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:s,end:/\{/}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,t("keyword","all\\b"),t("variable","@\\{"+r+"\\}"),{begin:"\\b("+qe.join("|")+")\\b",className:"selector-tag"},a.CSS_NUMBER_MODE,t("selector-tag",s,0),t("selector-id","#"+s),t("selector-class","\\."+s,0),t("selector-tag","&",0),a.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",begin:":("+He.join("|")+")"},{className:"selector-pseudo",begin:":(:)?("+Ze.join("|")+")"},{begin:/\(/,end:/\)/,relevance:0,contains:d},{begin:"!important"},a.FUNCTION_DISPATCH]},d={begin:r+":(:)?"+`(${i.join("|")})`,returnBegin:!0,contains:[s]};return o.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,c,l,d,u,s,g,a.FUNCTION_DISPATCH),{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:o}}function Xe(e){var n="\\[=*\\[",t="\\]=*\\]",a={begin:n,end:t,contains:["self"]},i=[e.COMMENT("--(?!"+n+")","$"),e.COMMENT("--"+n,t,{contains:[a],relevance:10})];return{name:"Lua",aliases:["pluto"],keywords:{$pattern:e.UNDERSCORE_IDENT_RE,literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},contains:i.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[e.inherit(e.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:i}].concat(i)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:n,end:t,contains:[a],relevance:5}])}}function Ve(e){var n={className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%\{/,end:/\}/},s={scope:"attr",match:/\s+:\s*\w+(\s*\(.*?\))?/},o={scope:"variable",variants:[{begin:/\$\d/},{begin:i.concat(/[$%@](?!")(\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,"(?![A-Za-z])(?![@$%])")},{begin:/[$%@](?!")[^\s\w{=]|\$=/,relevance:0}],contains:[s]},l={className:"number",variants:[{match:/0?\.[0-9][0-9_]+\b/},{match:/\bv?(0|[1-9][0-9_]*(\.[0-9_]+)?|[1-9][0-9_]*)\b/},{match:/\b0[0-7][0-7_]*\b/},{match:/\b0x[0-9a-fA-F][0-9a-fA-F_]*\b/},{match:/\b0b[0-1][0-1_]*\b/}],relevance:0},c=[e.BACKSLASH_ESCAPE,t,o],d=[/!/,/\//,/\|/,/\?/,/'/,/"/,/#/],g=(e,n,t="\\1")=>{var a="\\1"===t?t:i.concat(t,n);return i.concat(i.concat("(?:",e,")"),n,/(?:\\.|[^\\\/])*?/,a,/(?:\\.|[^\\\/])*?/,t,r)},u=(e,n,t)=>i.concat(i.concat("(?:",e,")"),n,/(?:\\.|[^\\\/])*?/,t,r),o=[o,e.HASH_COMMENT_MODE,e.COMMENT(/^=\w/,/=cut/,{endsWithParent:!0}),a,{className:"string",contains:c,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*<",end:">",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:/\{\w+\}/,relevance:0},{begin:"-?\\w+\\s*=>",relevance:0}]},l,{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",variants:[{begin:g("s|tr|y",i.either(...d,{capture:!0}))},{begin:g("s|tr|y","\\(","\\)")},{begin:g("s|tr|y","\\[","\\]")},{begin:g("s|tr|y","\\{","\\}")}],relevance:2},{className:"regexp",variants:[{begin:/(m|qr)\/\//,relevance:0},{begin:u("(?:m|qr)?",/\//,/\//)},{begin:u("m|qr",i.either(...d,{capture:!0}),/\1/)},{begin:u("m|qr",/\(/,/\)/)},{begin:u("m|qr",/\[/,/\]/)},{begin:u("m|qr",/\{/,/\}/)}]}]},{className:"function",beginKeywords:"sub method",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE,s]},{className:"class",beginKeywords:"class",end:"[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE,s,l]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return t.contains=o,{name:"Perl",aliases:["pl","pm"],keywords:n,contains:a.contains=o}}function Ye(e){var n=/[a-zA-Z@][a-zA-Z0-9_]*/,t={$pattern:n,keyword:["@interface","@class","@protocol","@implementation"]};return{name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"],keywords:{"variable.language":["this","super"],$pattern:n,keyword:["while","export","sizeof","typedef","const","struct","for","union","volatile","static","mutable","if","do","return","goto","enum","else","break","extern","asm","case","default","register","explicit","typename","switch","continue","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"],literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"],built_in:["dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"],type:["int","float","char","unsigned","signed","short","long","double","wchar_t","unichar","void","bool","BOOL","id|0","_Bool"]},illegal:"/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"("+t.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:t,contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}function en(e){var n=e.regex,t=/(?![A-Za-z0-9])(?![$])/,a=n.concat(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,t),i=n.concat(/(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/,t),t=n.concat(/[A-Z]+/,t),r={scope:"variable",match:"\\$+"+a},s={scope:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]},o=e.inherit(e.APOS_STRING_MODE,{illegal:null}),l="[ \t\n]",o={scope:"string",variants:[e.inherit(e.QUOTE_STRING_MODE,{illegal:null,contains:e.QUOTE_STRING_MODE.contains.concat(s)}),o,{begin:/<<<[ \t]*(?:(\w+)|"(\w+)")\n/,end:/[ \t]*(\w+)\b/,contains:e.QUOTE_STRING_MODE.contains.concat(s),"on:begin":(e,n)=>{n.data._beginMatch=e[1]||e[2]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}},e.END_SAME_AS_BEGIN({begin:/<<<[ \t]*'(\w+)'\n/,end:/[ \t]*(\w+)\b/})]},s={scope:"number",variants:[{begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?"}],relevance:0},c=["false","null","true"],d=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],g={keyword:h=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endswitch","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","switch","throw","trait","try","unset","use","var","void","while","xor","yield"],literal:(e=>{const n=[];return e.forEach(e=>{n.push(e),e.toLowerCase()===e?n.push(e.toUpperCase()):n.push(e.toLowerCase())}),n})(c),built_in:d},u=e=>e.map(e=>e.replace(/\|\d+$/,"")),b={variants:[{match:[/new/,n.concat(l,"+"),n.concat("(?!",u(d).join("\\b|"),"\\b)"),i],scope:{1:"keyword",4:"title.class"}}]},m=n.concat(a,"\\b(?!\\()"),m={variants:[{match:[n.concat(/::/,n.lookahead(/(?!class\b)/)),m],scope:{2:"variable.constant"}},{match:[/::/,/class/],scope:{2:"variable.language"}},{match:[i,n.concat(/::/,n.lookahead(/(?!class\b)/)),m],scope:{1:"title.class",3:"variable.constant"}},{match:[i,n.concat("::",n.lookahead(/(?!class\b)/))],scope:{1:"title.class"}},{match:[i,/::/,/class/],scope:{1:"title.class",3:"variable.language"}}]},p={scope:"attr",match:n.concat(a,n.lookahead(":"),n.lookahead(/(?!::)/))},f={relevance:0,begin:/\(/,end:/\)/,keywords:g,contains:[p,r,m,e.C_BLOCK_COMMENT_MODE,o,s,b]},h={relevance:0,match:[/\b/,n.concat("(?!fn\\b|function\\b|",u(h).join("\\b|"),"|",u(d).join("\\b|"),"\\b)"),a,n.concat(l,"*"),n.lookahead(/(?=\()/)],scope:{3:"title.function.invoke"},contains:[f]},u=(f.contains.push(h),[p,m,e.C_BLOCK_COMMENT_MODE,o,s,b]),d={begin:n.concat(/#\[\s*\\?/,n.either(i,t)),beginScope:"meta",end:/]/,endScope:"meta",keywords:{literal:c,keyword:["new","array"]},contains:[{begin:/\[/,end:/]/,keywords:{literal:c,keyword:["new","array"]},contains:["self",...u]},...u,{scope:"meta",variants:[{match:i},{match:t}]}]};return{case_insensitive:!1,keywords:g,contains:[d,e.HASH_COMMENT_MODE,e.COMMENT("//","$"),e.COMMENT("/\\*","\\*/",{contains:[{scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/,keywords:"__halt_compiler",starts:{scope:"comment",end:e.MATCH_NOTHING_RE,contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},{scope:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?=/},{begin:/<\?/,relevance:.1},{begin:/\?>/}]},{scope:"variable.language",match:/\$this\b/},r,h,m,{match:[/const/,/\s/,a],scope:{1:"keyword",3:"variable.constant"}},b,{scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use"},e.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:g,contains:["self",d,r,m,e.C_BLOCK_COMMENT_MODE,o,s]}]},{scope:"class",variants:[{beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"class interface trait",illegal:/[:($"]/}],relevance:0,end:/\{/,excludeEnd:!0,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",relevance:0,end:";",illegal:/[.']/,contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{scope:"title.class"})]},{beginKeywords:"use",relevance:0,end:";",contains:[{match:/\b(as|const|function)\b/,scope:"keyword"},e.UNDERSCORE_TITLE_MODE]},o,s]}}function nn(e){return{name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},e.inherit(e.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]}]}}function tn(e){return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}function an(e){var n=e.regex,t=/[\p{XID_Start}_]\p{XID_Continue}*/u,a={$pattern:/[A-Za-z]\w+|__\w+__/,keyword:l=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"],literal:["__debug__","Ellipsis","False","None","NotImplemented","True"],type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"]},i={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/,end:/\}/,keywords:a,illegal:/#/},s={begin:/\{\{/,relevance:0},s={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,i],relevance:10},{begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,i],relevance:10},{begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,i,s,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,i,s,r]},{begin:/([uU]|[rR])'/,end:/'/,relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/,end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,s,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},o=`(\\b(${c="[0-9](_?[0-9])*"}))?\\.(${c})|\\b(${c})\\.`,l="\\b|"+l.join("|"),o={className:"number",relevance:0,variants:[{begin:`(\\b(${c})|(${o}))[eE][+-]?(${c})[jJ]?(?=${l})`},{begin:`(${o})[jJ]?`},{begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${l})`},{begin:`\\b0[bB](_?[01])+[lL]?(?=${l})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${l})`},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${l})`},{begin:`\\b(${c})[jJ](?=${l})`}]},c={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:a,contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},l={className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:a,contains:["self",i,o,s,e.HASH_COMMENT_MODE]}]};return r.contains=[s,o,i],{name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:a,illegal:/(<\/|\?)|=>/,contains:[i,o,{scope:"variable.language",match:/\bself\b/},{beginKeywords:"if",relevance:0},{match:/\bor\b/,scope:"keyword"},s,c,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,t],scope:{1:"keyword",3:"title.function"},contains:[l]},{variants:[{match:[/\bclass/,/\s+/,t,/\s*/,/\(\s*/,t,/\s*\)/]},{match:[/\bclass/,/\s+/,t]}],scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[o,l,s]}]}}function rn(e){return{aliases:["pycon"],contains:[{className:"meta.prompt",starts:{end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}}function sn(e){var n=e.regex,t=/(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/,a=n.either(/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/,/0[xX][0-9a-fA-F]+(?:[pP][+-]?\d+)?[Li]?/,/(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?[Li]?/),i=/[=!<>:]=|\|\||&&|:::?|<-|<<-|->>|->|\|>|[-+*\/?!$&|:<=>@^~]|\*\*/,r=n.either(/[()]/,/[{}]/,/\[\[/,/[[\]]/,/\\/,/,/);return{name:"R",keywords:{$pattern:t,keyword:"function if in break next repeat else for while",literal:"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10",built_in:"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm"},contains:[e.COMMENT(/#'/,/$/,{contains:[{scope:"doctag",match:/@examples/,starts:{end:n.lookahead(n.either(/\n^#'\s*(?=@[a-zA-Z]+)/,/\n^(?!#')/)),endsParent:!0}},{scope:"doctag",begin:"@param",end:/$/,contains:[{scope:"variable",variants:[{match:t},{match:/`(?:\\.|[^`\\])+`/}],endsParent:!0}]},{scope:"doctag",match:/@[a-zA-Z]+/},{scope:"keyword",match:/\\[a-zA-Z]+/}]}),e.HASH_COMMENT_MODE,{scope:"string",contains:[e.BACKSLASH_ESCAPE],variants:[e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\(/,end:/\)(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\{/,end:/\}(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\[/,end:/\](-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\(/,end:/\)(-*)'/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\{/,end:/\}(-*)'/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\[/,end:/\](-*)'/}),{begin:'"',end:'"',relevance:0},{begin:"'",end:"'",relevance:0}]},{relevance:0,variants:[{scope:{1:"operator",2:"number"},match:[i,a]},{scope:{1:"operator",2:"number"},match:[/%[^%]*%/,a]},{scope:{1:"punctuation",2:"number"},match:[r,a]},{scope:{2:"number"},match:[/[^a-zA-Z0-9._]|^/,a]}]},{scope:{3:"operator"},match:[t,/\s+/,/<-/,/\s+/]},{scope:"operator",relevance:0,variants:[{match:i},{match:/%[^%]*%/}]},{scope:"punctuation",relevance:0,match:r},{begin:"`",end:"`",contains:[{begin:/\\./}]}]}}function on(e){var n=e.regex,t=/(r#)?/,a=n.concat(t,e.UNDERSCORE_IDENT_RE),t=n.concat(t,e.IDENT_RE),t={className:"title.function.invoke",relevance:0,begin:n.concat(/\b/,/(?!let|for|while|if|else|match\b)/,t,n.lookahead(/\s*\(/))},n="([ui](8|16|32|64|128|size)|f(32|64))?",i=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","eprintln!","panic!","file!","format!","format_args!","include_bytes!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"],r=["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"];return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",type:r,keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","union","unsafe","unsized","use","virtual","where","while","yield"],literal:["true","false","Some","None","Ok","Err"],built_in:i},illegal:""},t]}}const ln=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],cn=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),dn=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),gn=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),un=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-align","box-decoration-break","box-direction","box-flex","box-flex-group","box-lines","box-ordinal-group","box-orient","box-pack","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","contain-intrinsic-block-size","contain-intrinsic-height","contain-intrinsic-inline-size","contain-intrinsic-size","contain-intrinsic-width","container","container-name","container-type","content","content-visibility","counter-increment","counter-reset","counter-set","cue","cue-after","cue-before","cursor","cx","cy","direction","display","dominant-baseline","empty-cells","enable-background","field-sizing","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flood-color","flood-opacity","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-palette","font-size","font-size-adjust","font-smooth","font-smoothing","font-stretch","font-style","font-synthesis","font-synthesis-position","font-synthesis-small-caps","font-synthesis-style","font-synthesis-weight","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-emoji","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","forced-color-adjust","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphenate-character","hyphenate-limit-chars","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","initial-letter","initial-letter-align","inline-size","inset","inset-area","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","kerning","left","letter-spacing","lighting-color","line-break","line-height","line-height-step","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","margin-trim","marker","marker-end","marker-mid","marker-start","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","masonry-auto-flow","math-depth","math-shift","math-style","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-anchor","overflow-block","overflow-clip-margin","overflow-inline","overflow-wrap","overflow-x","overflow-y","overlay","overscroll-behavior","overscroll-behavior-block","overscroll-behavior-inline","overscroll-behavior-x","overscroll-behavior-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","paint-order","pause","pause-after","pause-before","perspective","perspective-origin","place-content","place-items","place-self","pointer-events","position","position-anchor","position-visibility","print-color-adjust","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","ruby-align","ruby-position","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scroll-timeline","scroll-timeline-axis","scroll-timeline-name","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","speak","speak-as","src","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","tab-size","table-layout","text-align","text-align-all","text-align-last","text-anchor","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-size-adjust","text-transform","text-underline-offset","text-underline-position","text-wrap","text-wrap-mode","text-wrap-style","timeline-scope","top","touch-action","transform","transform-box","transform-origin","transform-style","transition","transition-behavior","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","user-modify","user-select","vector-effect","vertical-align","view-timeline","view-timeline-axis","view-timeline-inset","view-timeline-name","view-transition-name","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","white-space-collapse","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index","zoom"].sort().reverse();function bn(e){var n={IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/}},t=gn,a=dn,i="@[a-z-]+",r={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b",relevance:0};return{name:"SCSS",case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n.CSS_NUMBER_MODE,{className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-tag",begin:"\\b("+ln.join("|")+")\\b",relevance:0},{className:"selector-pseudo",begin:":("+a.join("|")+")"},{className:"selector-pseudo",begin:":(:)?("+t.join("|")+")"},r,{begin:/\(/,end:/\)/,contains:[n.CSS_NUMBER_MODE]},n.CSS_VARIABLE,{className:"attribute",begin:"\\b("+un.join("|")+")\\b"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:/:/,end:/[;}{]/,relevance:0,contains:[n.BLOCK_COMMENT,r,n.HEXCOLOR,n.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.IMPORTANT,n.FUNCTION_DISPATCH]},{begin:"@(page|font-face)",keywords:{$pattern:i,keyword:"@page @font-face"}},{begin:"@",end:"[{;]",returnBegin:!0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:cn.join(" ")},contains:[{begin:i,className:"keyword"},{begin:/[a-z-]+(?=:)/,className:"attribute"},r,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.HEXCOLOR,n.CSS_NUMBER_MODE]},n.FUNCTION_DISPATCH]}}function mn(e){return{name:"Shell Session",aliases:["console","shellsession"],contains:[{className:"meta.prompt",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}}function pn(e){const n=e.regex;var t=e.COMMENT("--","$");const a=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"];var i=a,r=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter(e=>!a.includes(e)),i={match:n.concat(/\b/,n.either(...i),/\s*\(/),relevance:0,keywords:{built_in:i}};function s(e){return n.concat(/\b/,n.either(...e.map(e=>e.replace(/\s+/,"\\s+"))),/\b/)}var o={scope:"keyword",match:s(["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"]),relevance:0};return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{$pattern:/\b[\w\.]+/,keyword:function(e,{exceptions:n,when:t}){const a=t;return n=n||[],e.map(e=>!e.match(/\|\d+$/)&&!n.includes(e)&&a(e)?e+"|0":e)}(r,{when:e=>e.length<3}),literal:["true","false","unknown"],type:["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"]},contains:[{scope:"type",match:s(["double precision","large object","with timezone","without timezone"])},o,i,{scope:"variable",match:/@[a-z0-9][a-z0-9_]*/},{scope:"string",variants:[{begin:/'/,end:/'/,contains:[{match:/''/}]}]},{begin:/"/,end:/"/,contains:[{match:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{scope:"operator",match:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}function fn(e){return e?"string"==typeof e?e:e.source:null}function k(e){return N("(?=",e,")")}function N(...e){return e.map(e=>fn(e)).join("")}function x(...e){var n,t="object"==typeof(n=(t=e)[t.length-1])&&n.constructor===Object?(t.splice(t.length-1,1),n):{};return"("+(t.capture?"":"?:")+e.map(e=>fn(e)).join("|")+")"}const O=e=>N(/\b/,e,/\w$/.test(e)?/\b/:/\B/),hn=["Protocol","Type"].map(O),_n=["init","self"].map(O),yn=["Any","Self"],M=["actor","any","associatedtype","async","await",/as\?/,/as!/,"as","borrowing","break","case","catch","class","consume","consuming","continue","convenience","copy","default","defer","deinit","didSet","distributed","do","dynamic","each","else","enum","extension","fallthrough",/fileprivate\(set\)/,"fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout",/internal\(set\)/,"internal","in","is","isolated","nonisolated","lazy","let","macro","mutating","nonmutating",/open\(set\)/,"open","operator","optional","override","package","postfix","precedencegroup","prefix",/private\(set\)/,"private","protocol",/public\(set\)/,"public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias",/unowned\(safe\)/,/unowned\(unsafe\)/,"unowned","var","weak","where","while","willSet"],vn=["false","nil","true"],En=["assignment","associativity","higherThan","left","lowerThan","none","right"],wn=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warning"],kn=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"];d=x(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/);const Nn=x(d,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),A=N(d,Nn,"*");a=x(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFEFE\uFF00-\uFFFD]/);const S=x(a,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),C=N(a,S,"*"),T=N(/[A-Z]/,S,"*"),xn=["attached","autoclosure",N(/convention\(/,x("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","freestanding","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",N(/objc\(/,C,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","resultBuilder","Sendable","testable","UIApplicationMain","unchecked","unknown","usableFromInline","warn_unqualified_access"],On=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"];function Mn(e){var n={match:/\s+/,relevance:0},t=e.COMMENT("/\\*","\\*/",{contains:["self"]}),t=[e.C_LINE_COMMENT_MODE,t],a={match:[/\./,x(...hn,..._n)],className:{2:"keyword"}},i={match:N(/\./,x(...M)),relevance:0},r=M.filter(e=>"string"==typeof e).concat(["_|0"]),s={variants:[{className:"keyword",match:x(...M.filter(e=>"string"!=typeof e).concat(yn).map(O),..._n)}]},o={$pattern:x(/\b\w+/,/#\w+/),keyword:r.concat(wn),literal:vn},l=[a,i,s],c=[{match:N(/\./,x(...kn)),relevance:0},{className:"built_in",match:N(/\b/,x(...kn),/(?=\()/)}],d=[r={match:/->/,relevance:0},{className:"operator",relevance:0,variants:[{match:A},{match:`\\.(\\.|${Nn})+`}]}],g={className:"number",relevance:0,variants:[{match:`\\b(${a="([0-9]_*)+"})(\\.(${a}))?`+`([eE][+-]?(${a}))?\\b`},{match:`\\b0x(${i="([0-9a-fA-F]_*)+"})(\\.(${i}))?`+`([pP][+-]?(${a}))?\\b`},{match:/\b0o([0-7]_*)+\b/},{match:/\b0b([01]_*)+\b/}]};const u=(e="")=>({className:"subst",variants:[{match:N(/\\/,e,/[0\\tnr"']/)},{match:N(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),b=(e="")=>({className:"subst",label:"interpol",begin:N(/\\/,e,/\(/),end:/\)/});var i=(e="")=>({begin:N(e,/"/),end:N(/"/,e),contains:[u(e),b(e)]}),m={className:"string",variants:[(s=(e="")=>{return{begin:N(e,/"""/),end:N(/"""/,e),contains:[u(e),([n=""]=[e],{className:"subst",match:N(/\\/,n,/[\t ]*(?:[\r\n]|\r\n)/)}),b(e)]};var n})(),s("#"),s("##"),s("###"),i(),i("#"),i("##"),i("###")]};const p=[e.BACKSLASH_ESCAPE,{begin:/\[/,end:/\]/,relevance:0,contains:[e.BACKSLASH_ESCAPE]}];var a={begin:/\/[^\s](?=[^/\n]*\/)/,end:/\//,contains:p},i={scope:"regexp",variants:[(s=e=>{var n=N(e,/\//),e=N(/\//,e);return{begin:n,end:e,contains:[...p,{scope:"comment",begin:`#(?!.*${e})`,end:/$/}]}})("###"),s("##"),s("#"),a]},f=[e={match:N(/`/,C,/`/)},{className:"variable",match:/\$\d+/},{className:"variable",match:`\\$${S}+`}],s=[{match:/(@|#(un)?)available/,scope:"keyword",starts:{contains:[{begin:/\(/,end:/\)/,keywords:On,contains:[...d,g,m]}]}},{scope:"keyword",match:N(/@/,x(...xn),k(x(/\(/,/\s+/)))},{scope:"meta",match:N(/@/,C)}],a={match:k(/\b[A-Z]/),relevance:0,contains:[{className:"type",match:N(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,S,"+")},{className:"type",match:T,relevance:0},{match:/[?!]+/,relevance:0},{match:/\.\.\./,relevance:0},{match:N(/\s+&\s+/,k(T)),relevance:0}]},r={begin://,keywords:o,contains:[...t,...l,...s,r,a]},r=(a.contains.push(r),{match:N(C,/\s*:/),keywords:"_|0",relevance:0}),r={begin:/\(/,end:/\)/,relevance:0,keywords:o,contains:["self",r,...t,i,...l,...c,...d,g,m,...f,...s,a]},h={begin://,keywords:"repeat each",contains:[...t,a]},_={begin:/\(/,end:/\)/,keywords:o,contains:[{begin:x(k(N(C,/\s*:/)),k(N(C,/\s+/,C,/\s*:/))),end:/:/,relevance:0,contains:[{className:"keyword",match:/\b_\b/},{className:"params",match:C}]},...t,...l,...d,g,m,...s,a,r],endsParent:!0,illegal:/["']/},e={match:[/(func|macro)/,/\s+/,x(e.match,C,A)],className:{1:"keyword",3:"title.function"},contains:[h,_,n],illegal:[/\[/,/%/]},_={match:[/\b(?:subscript|init[?!]?)/,/\s*(?=[<(])/],className:{1:"keyword"},contains:[h,_,n],illegal:/\[|%/},n={match:[/operator/,/\s+/,A],className:{1:"keyword",3:"title"}},y={begin:[/precedencegroup/,/\s+/,T],className:{1:"keyword",3:"title"},contains:[a],keywords:[...En,...vn],end:/}/},h={begin:[/(struct|protocol|class|extension|enum|actor)/,/\s+/,C,/\s*/],beginScope:{1:"keyword",3:"title.class"},keywords:o,contains:[h,...l,{begin:/:/,end:/\{/,keywords:o,contains:[{scope:"title.class.inherited",match:T},...l],relevance:0}]};for(const w of m.variants){var v=w.contains.find(e=>"interpol"===e.label),E=(v.keywords=o,[...l,...c,...d,g,m,...f]);v.contains=[...E,{begin:/\(/,end:/\)/,contains:["self",...E]}]}return{name:"Swift",keywords:o,contains:[...t,e,_,{match:[/class\b/,/\s+/,/func\b/,/\s+/,/\b[A-Za-z_][A-Za-z0-9_]*\b/],scope:{1:"keyword",3:"keyword",5:"title.function"}},{match:[/class\b/,/\s+/,/var\b/],scope:{1:"keyword",3:"keyword"}},h,n,y,{beginKeywords:"import",end:/$/,contains:[...t],relevance:0},i,...l,...c,...d,g,m,...f,...s,a,r]}}function An(e){var n="true false yes no null",t="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(a,{variants:[{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),r={end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},t=[{className:"attr",variants:[{begin:/[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/},{begin:/"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/},{begin:/'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+t},{className:"type",begin:"!<"+t+">"},{className:"type",begin:"!"+t},{className:"type",begin:"!!"+t},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},{begin:/\{/,end:/\}/,contains:[r],illegal:"\\n",relevance:0},{begin:"\\[",end:"\\]",contains:[r],illegal:"\\n",relevance:0},{className:"string",relevance:0,begin:/'/,end:/'/,contains:[{match:/''/,scope:"char.escape",relevance:0}]},a];return(n=[...t]).pop(),n.push(i),r.contains=n,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:t}}const R="[A-Za-z$_][0-9A-Za-z$_]*",Sn=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends","using"],Cn=["true","false","null","undefined","NaN","Infinity"],Tn=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],Rn=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],Dn=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],In=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],Ln=[].concat(Dn,Tn,Rn);function Bn(e){const n=e.regex;var t=R;const a="<>",i="";const r=/<[A-Za-z0-9\\._:-]+/,s=/\/[A-Za-z0-9\\._:-]+>|\/>/,o=(e,n)=>{var t,a,i=e[0].length+e.index,r=e.input[i];("<"===r||","===r||(">"===r&&([r,t]=[e,{after:i}["after"]],a="e+"\\s*\\("),n.concat("(?!",v.join("|"),")")),t,n.lookahead(/\s*\(/)),className:"title.function",relevance:0},E={begin:n.concat(/\./,n.lookahead(n.concat(t,/(?![0-9A-Za-z$_(])/))),end:t,excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},w={match:[/get|set/,/\s+/,t,/(?=\()/],className:{1:"keyword",3:"title.function"},contains:[{begin:/\(\)/},f]},k="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+e.UNDERSCORE_IDENT_RE+")\\s*=>",N={match:[/const|var|let/,/\s+/,t,/\s*/,/=\s*/,/(async\s*)?/,n.lookahead(k)],keywords:"async",className:{1:"keyword",3:"title.function"},contains:[f]};return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:l,exports:{PARAMS_CONTAINS:g,CLASS_REFERENCE:_},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:"shebang",binary:"node",relevance:5}),{label:"use_strict",className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,d,u,b,m,p,{match:/\$\d+/},c,_,{scope:"attr",match:t+n.lookahead(":"),relevance:0},N,{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",relevance:0,contains:[p,e.REGEXP_MODE,{className:"function",begin:k,returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/(\s*)\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:l,contains:g}]}]},{begin:/,/,relevance:0},{match:/\s+/,relevance:0},{variants:[{begin:a,end:i},{match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:r,"on:begin":o,end:s}],subLanguage:"xml",contains:[{begin:r,end:s,skip:!0,contains:["self"]}]}]},y,{beginKeywords:"while if switch catch for"},{begin:"\\b(?!function)"+e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,label:"func.def",contains:[f,e.inherit(e.TITLE_MODE,{begin:t,className:"title.function"})]},{match:/\.\.\./,relevance:0},E,{match:"\\$"+t,relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},contains:[f]},v,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},h,w,{match:/\$[(.]/}]}}function zn(e){var n=e.regex,t=Bn(e),a=R,i=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],r={begin:[/namespace/,/\s+/,e.IDENT_RE],beginScope:{1:"keyword",3:"title.class"}},s={beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:{keyword:"interface extends",built_in:i},contains:[t.exports.CLASS_REFERENCE]},i={$pattern:R,keyword:Sn.concat(["type","interface","public","private","protected","implements","declare","abstract","readonly","enum","override","satisfies"]),literal:Cn,built_in:Ln.concat(i),"variable.language":In},o={className:"meta",begin:"@"+a},l=(e,n,t)=>{var a=e.contains.findIndex(e=>e.label===n);if(-1===a)throw new Error("can not find mode to replace");e.contains.splice(a,1,t)},i=(Object.assign(t.keywords,i),t.exports.PARAMS_CONTAINS.push(o),t.contains.find(e=>"attr"===e.scope)),a=Object.assign({},i,{match:n.concat(a,n.lookahead(/\s*\?:/))});return t.exports.PARAMS_CONTAINS.push([t.exports.CLASS_REFERENCE,i,a]),t.contains=t.contains.concat([o,r,s,a]),l(t,"shebang",e.SHEBANG()),l(t,"use_strict",{className:"meta",relevance:10,begin:/^\s*['"]use strict['"]/}),t.contains.find(e=>"func.def"===e.label).relevance=0,Object.assign(t,{name:"TypeScript",aliases:["ts","tsx","mts","cts"]}),t}function $n(e){var n=e.regex,t=/\d{1,2}\/\d{1,2}\/\d{4}/,a=/\d{4}-\d{1,2}-\d{1,2}/,i=/(\d|1[012])(:\d+){0,2} *(AM|PM)/,r=/\d{1,2}(:\d{1,2}){1,2}/,a={className:"literal",variants:[{begin:n.concat(/# */,n.either(a,t),/ *#/)},{begin:n.concat(/# */,r,/ *#/)},{begin:n.concat(/# */,i,/ *#/)},{begin:n.concat(/# */,n.either(a,t),/ +/,n.either(i,r),/ *#/)}]},t=e.COMMENT(/'''/,/$/,{contains:[{className:"doctag",begin:/<\/?/,end:/>/}]}),n=e.COMMENT(null,/$/,{variants:[{begin:/'/},{begin:/([\t ]|^)REM(?=\s)/}]});return{name:"Visual Basic .NET",aliases:["vb"],case_insensitive:!0,classNameAliases:{label:"symbol"},keywords:{keyword:"addhandler alias aggregate ansi as async assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into iterator join key let lib loop me mid module mustinherit mustoverride mybase myclass namespace narrowing new next notinheritable notoverridable of off on operator option optional order overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly yield",built_in:"addressof and andalso await directcast gettype getxmlnamespace is isfalse isnot istrue like mod nameof new not or orelse trycast typeof xor cbool cbyte cchar cdate cdbl cdec cint clng cobj csbyte cshort csng cstr cuint culng cushort",type:"boolean byte char date decimal double integer long object sbyte short single string uinteger ulong ushort",literal:"true false nothing"},illegal:"//|\\{|\\}|endif|gosub|variant|wend|^\\$ ",contains:[{className:"string",begin:/"(""|[^/n])"C\b/},{className:"string",begin:/"/,end:/"/,illegal:/\n/,contains:[{begin:/""/}]},a,{className:"number",relevance:0,variants:[{begin:/\b\d[\d_]*((\.[\d_]+(E[+-]?[\d_]+)?)|(E[+-]?[\d_]+))[RFD@!#]?/},{begin:/\b\d[\d_]*((U?[SIL])|[%&])?/},{begin:/&H[\dA-F_]+((U?[SIL])|[%&])?/},{begin:/&O[0-7_]+((U?[SIL])|[%&])?/},{begin:/&B[01_]+((U?[SIL])|[%&])?/}]},{className:"label",begin:/^\w+:/},t,n,{className:"meta",begin:/[\t ]*#(const|disable|else|elseif|enable|end|externalsource|if|region)\b/,end:/$/,keywords:{keyword:"const disable else elseif enable end externalsource if region then"},contains:[n]}]}}function Fn(e){e.regex;var n=e.COMMENT(/\(;/,/;\)/),t=(n.contains.push("self"),e.COMMENT(/;;/,/$/));return{name:"WebAssembly",keywords:{$pattern:/[\w.]+/,keyword:["anyfunc","block","br","br_if","br_table","call","call_indirect","data","drop","elem","else","end","export","func","global.get","global.set","local.get","local.set","local.tee","get_global","get_local","global","if","import","local","loop","memory","memory.grow","memory.size","module","mut","nop","offset","param","result","return","select","set_global","set_local","start","table","tee_local","then","type","unreachable"]},contains:[t,n,{match:[/(?:offset|align)/,/\s*/,/=/],className:{1:"keyword",3:"operator"}},{className:"variable",begin:/\$[\w_]+/},{match:/(\((?!;)|\))+/,className:"punctuation",relevance:0},{begin:[/(?:func|call|call_indirect)/,/\s+/,/\$[^\s)]+/],className:{1:"keyword",3:"title.function"}},e.QUOTE_STRING_MODE,{match:/(i32|i64|f32|f64)(?!\.)/,className:"type"},{className:"keyword",match:/\b(f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|nearest|neg?|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|store(?:8|16|32)?|sqrt|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))\b/},{className:"number",relevance:0,match:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/}]}}o.registerLanguage("xml",ue),o.registerLanguage("bash",be),o.registerLanguage("c",me),o.registerLanguage("cpp",pe),o.registerLanguage("csharp",fe),o.registerLanguage("css",we),o.registerLanguage("markdown",ke),o.registerLanguage("diff",Ne),o.registerLanguage("ruby",xe),o.registerLanguage("go",Oe),o.registerLanguage("graphql",Me),o.registerLanguage("ini",Ae),o.registerLanguage("java",Ce),o.registerLanguage("javascript",Fe),o.registerLanguage("json",je),o.registerLanguage("kotlin",Pe),o.registerLanguage("less",Qe),o.registerLanguage("lua",Xe),o.registerLanguage("makefile",Ve),o.registerLanguage("perl",Je),o.registerLanguage("objectivec",Ye),o.registerLanguage("php",en),o.registerLanguage("php-template",nn),o.registerLanguage("plaintext",tn),o.registerLanguage("python",an),o.registerLanguage("python-repl",rn),o.registerLanguage("r",sn),o.registerLanguage("rust",on),o.registerLanguage("scss",bn),o.registerLanguage("shell",mn),o.registerLanguage("sql",pn),o.registerLanguage("swift",Mn),o.registerLanguage("yaml",An),o.registerLanguage("typescript",zn),o.registerLanguage("vbnet",$n),o.registerLanguage("wasm",Fn);var E=(o.HighlightJS=o).default=o,w={exports:{}},i=function(){"use strict";const l=new Set(["auto","register","static","extern","mutable","thread_local","const","volatile","constexpr","consteval","constinit","void","bool","char","short","int","long","float","double","signed","unsigned","wchar_t","char8_t","char16_t","char32_t","class","struct","union","enum","typename","typedef","if","else","switch","case","default","for","while","do","break","continue","return","goto","try","catch","throw","noexcept","public","private","protected","virtual","override","final","friend","this","operator","new","delete","template","concept","requires","namespace","using","sizeof","alignof","alignas","decltype","typeid","static_cast","dynamic_cast","const_cast","reinterpret_cast","static_assert","inline","explicit","export","module","import","co_await","co_yield","co_return","true","false","nullptr","NULL"]);function c(e){return e.replace(/&/g,"&").replace(//g,">")}function d(e,n){return`${c(n)}`}function n(t){var a=[];let i=0;for(var r=t.length;i + + + + + + + + + + + + + Capy :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + +
+
+
+ +

Capy

+
+
+
+

Capy abstracts away sockets, files, and asynchrony with type-erased streams and buffer sequences—code compiles fast because the implementation is hidden. It provides the framework for concurrent algorithms that transact in buffers of memory: networking, serial ports, console, timers, and any platform I/O. This is only possible because Capy is coroutine-only, enabling optimizations and ergonomics that hybrid approaches must sacrifice.

+
+
+
+
+

What This Library Does

+
+
+
    +
  • +

    Lazy coroutine taskstask<T> with forward-propagating stop tokens and automatic cancellation

    +
  • +
  • +

    Buffer sequences — taken straight from Asio and improved

    +
  • +
  • +

    Stream conceptsReadStream, WriteStream, ReadSource, WriteSink, BufferSource, BufferSink

    +
  • +
  • +

    Type-erased streamsany_stream, any_read_stream, any_write_stream for fast compilation

    +
  • +
  • +

    Concurrency facilities — executors, strands, thread pools, when_all, when_any

    +
  • +
  • +

    Test utilities — mock streams, mock sources/sinks, error injection

    +
  • +
+
+
+
+
+

What This Library Does Not Do

+
+
+
    +
  • +

    Networking — no sockets, acceptors, or DNS; that’s what Corosio provides

    +
  • +
  • +

    Protocols — no HTTP, WebSocket, or TLS; see the Http and Beast2 libraries

    +
  • +
  • +

    Platform event loops — no io_uring, IOCP, epoll, or kqueue; Capy is the layer above

    +
  • +
  • +

    Callbacks or futures — coroutine-only means no other continuation styles

    +
  • +
  • +

    Sender/receiver — Capy uses the IoAwaitable protocol, not std::execution

    +
  • +
+
+
+
+
+

Target Audience

+
+
+
    +
  • +

    Users of Corosio — portable coroutine networking

    +
  • +
  • +

    Users of Http — sans-I/O HTTP/1.1 clients and servers

    +
  • +
  • +

    Users of Websocket — sans-I/O WebSocket

    +
  • +
  • +

    Users of Beast2 — high-level HTTP/WebSocket servers

    +
  • +
  • +

    Users of Burl — high-level HTTP client

    +
  • +
+
+
+

All of these are built on Capy. Understanding its concepts—tasks, buffer sequences, streams, executors—unlocks the full power of the stack.

+
+
+
+
+

Design Philosophy

+
+
+
    +
  • +

    Use case first. Buffer sequences, stream concepts, executor affinity—these exist because I/O code needs them, not because they’re theoretically elegant.

    +
  • +
  • +

    Coroutines-only. No callbacks, futures, or sender/receiver. Hybrid support forces compromises; full commitment unlocks optimizations that adapted models cannot achieve.

    +
  • +
  • +

    Address the complaints of C++. Type erasure at boundaries, minimal dependencies, and hidden implementations keep builds fast and templates manageable.

    +
  • +
+
+
+
+
+

Requirements

+
+
+

Assumed Knowledge

+
+
    +
  • +

    C++20 coroutines, concepts, and ranges

    +
  • +
  • +

    Basic concurrent programming

    +
  • +
+
+
+
+

Compiler Support

+
+
    +
  • +

    GCC 12+

    +
  • +
  • +

    Clang 17+

    +
  • +
  • +

    Apple-Clang (macOS 14+)

    +
  • +
  • +

    MSVC 14.34+

    +
  • +
  • +

    MinGW

    +
  • +
+
+
+
+

Dependencies

+
+

None. Capy is self-contained and does not require Boost.

+
+
+
+

Linking

+
+

Capy is a compiled library. Link against capy.

+
+
+
+
+
+

Code Convention

+
+
+ + + + + +
+ + +
+

Unless otherwise specified, all code examples in this documentation assume the following:

+
+
+
+
#include <boost/capy.hpp>
+using namespace boost::capy;
+
+
+
+
+
+
+
+

Quick Example

+
+
+

This example demonstrates a minimal coroutine that reads from a stream and echoes the data back:

+
+
+
+
#include <boost/capy.hpp>
+
+using namespace boost::capy;
+
+task<> echo(any_stream& stream)
+{
+    char buf[1024];
+    for(;;)
+    {
+        auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+        if(ec.failed())
+            co_return;
+        auto [wec, wn] = co_await write(stream, const_buffer(buf, n));
+        if(wec.failed())
+            co_return;
+    }
+}
+
+int main()
+{
+    thread_pool pool;
+    // In a real application, you would obtain a stream from Corosio
+    // and call: run_async(pool.get_executor())(echo(stream));
+    return 0;
+}
+
+
+
+

The echo function accepts an any_stream&—a type-erased wrapper that works with any concrete stream implementation. The function reads data into a buffer, then writes it back. Both operations use co_await to suspend until the I/O completes.

+
+
+

The task<> return type (equivalent to task<void>) creates a lazy coroutine that does not start executing until awaited or launched with run_async.

+
+
+
+
+

Next Steps

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/quick-start.html b/preview/quick-start.html new file mode 100644 index 0000000..ffdf34f --- /dev/null +++ b/preview/quick-start.html @@ -0,0 +1,550 @@ + + + + + + + + + + + + + + Quick Start :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Quick Start

+
+
+
+

This page gets you from zero to a working coroutine program in five minutes.

+
+
+ + + + + +
+ + +Capy requires C++20 with coroutine support. +
+
+
+
+
+

Minimal Example

+
+
+

Create a file hello_coro.cpp:

+
+
+
+
#include <boost/capy/task.hpp>
+#include <boost/capy/ex/run_async.hpp>
+#include <boost/capy/ex/thread_pool.hpp>
+#include <iostream>
+
+namespace capy = boost::capy;
+
+// A coroutine that returns a value
+capy::task<int> answer()
+{
+    co_return 42;
+}
+
+// A coroutine that awaits another coroutine
+capy::task<void> greet()
+{
+    int n = co_await answer();
+    std::cout << "The answer is " << n << "\n";
+}
+
+int main()
+{
+    capy::thread_pool pool(1);
+
+    // Launch the coroutine on the pool's executor
+    capy::run_async(pool.get_executor())(greet());
+
+    // Pool destructor waits for all work to complete
+}
+
+
+
+
+
+

Build and Run

+
+
+
+
# With GCC
+g++ -std=c++20 -o hello_coro hello_coro.cpp -lboost_system -pthread
+
+# Run
+./hello_coro
+
+
+
+

Expected output:

+
+
+
+
The answer is 42
+
+
+
+
+
+

What Just Happened?

+
+
+
    +
  1. +

    answer() creates a suspended coroutine that will return 42

    +
  2. +
  3. +

    greet() creates a suspended coroutine that will await answer()

    +
  4. +
  5. +

    run_async(executor)(greet()) starts greet() on the pool’s executor

    +
  6. +
  7. +

    greet() runs until it hits co_await answer()

    +
  8. +
  9. +

    answer() runs and returns 42

    +
  10. +
  11. +

    greet() resumes with the result and prints it

    +
  12. +
  13. +

    greet() completes, the pool destructor waits and returns

    +
  14. +
+
+
+

The key insight: both coroutines ran on the same executor because affinity +propagated automatically through the co_await.

+
+
+
+
+

Handling Results

+
+
+

To receive a task’s result outside a coroutine, provide a completion handler:

+
+
+
+
capy::run_async(executor)(answer(), [](int result) {
+    std::cout << "Got: " << result << "\n";
+});
+
+
+
+
+
+

Handling Errors

+
+
+

Exceptions propagate through coroutine chains. To handle them at the top level:

+
+
+
+
capy::run_async(executor)(might_fail(),
+    [](int result) {
+        std::cout << "Success: " << result << "\n";
+    },
+    [](std::exception_ptr ep) {
+        try {
+            if (ep) std::rethrow_exception(ep);
+        } catch (std::exception const& e) {
+            std::cerr << "Error: " << e.what() << "\n";
+        }
+    }
+);
+
+
+
+
+
+

Next Steps

+
+
+

Now that you have a working program:

+
+
+ +
+
+
+ + +
+
+ +
+ + diff --git a/preview/reference/boost.html b/preview/reference/boost.html new file mode 100644 index 0000000..b44568e --- /dev/null +++ b/preview/reference/boost.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy.html b/preview/reference/boost/capy.html new file mode 100644 index 0000000..fc6426f --- /dev/null +++ b/preview/reference/boost/capy.html @@ -0,0 +1,998 @@ + + + + + + + + + + + + + + boost::capy :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy

+
+

Namespaces

+
+ ++++ + + + + + + + + + + +

Name

Description

this_coro

Namespace for coroutine environment accessors.

+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_buffer_sink

Type‐erased wrapper for any BufferSink.

any_buffer_source

Type‐erased wrapper for any BufferSource.

any_executor

A type‐erased wrapper for executor objects.

any_read_source

Type‐erased wrapper for any ReadSource.

any_read_stream

Type‐erased wrapper for any ReadStream.

any_stream

Type‐erased wrapper for bidirectional streams.

any_write_sink

Type‐erased wrapper for any WriteSink.

any_write_stream

Type‐erased wrapper for any WriteStream.

async_event

An asynchronous event for coroutines.

async_mutex

An asynchronous mutex for coroutines.

basic_string_dynamic_buffer

A dynamic buffer using an underlying string

basic_vector_dynamic_buffer

A dynamic buffer using an underlying vector.

basic_vector_dynamic_buffer

A dynamic buffer using an underlying vector.

begin_mrdocs_workaround_t

Return an iterator to the first buffer in a sequence.

buffer_array

A buffer sequence holding up to N buffers.

buffer_copy_mrdocs_workaround_t

Copy the contents of a buffer sequence into another buffer sequence.

buffer_empty_mrdocs_workaround_t

Check if a buffer sequence contains no data.

buffer_param

A buffer sequence wrapper providing windowed access.

buffer_param

A buffer sequence wrapper providing windowed access.

buffer_size_mrdocs_workaround_t

Return the total byte count across all buffers in a sequence.

circular_dynamic_buffer

A fixed‐capacity circular buffer satisfying DynamicBuffer.

const_buffer

A reference to a contiguous region of read‐only memory.

const_buffer_archetype_

Archetype for ConstBufferSequence concept checking.

consuming_buffers

Wrapper for consuming a buffer sequence incrementally.

consuming_buffers

Wrapper for consuming a buffer sequence incrementally.

end_mrdocs_workaround_t

Return an iterator past the last buffer in a sequence.

execution_context

Base class for I/O object containers providing service management.

executor_ref

A type‐erased reference wrapper for executor objects.

flat_dynamic_buffer

A fixed‐capacity linear buffer satisfying DynamicBuffer.

front_mrdocs_workaround_t

Return the first buffer in a sequence.

immediate

An awaitable that completes immediately with a value.

io_awaitable_promise_base

CRTP mixin that adds I/O awaitable support to a promise type.

io_env

Execution environment for IoAwaitables.

io_result<>

Result type for void operations.

io_result

Result type for asynchronous I/O operations.

io_result<T1>

Result type for byte transfer operations.

io_result<T1, T2>

io_result<T1, T2, T3>

keep_prefix_mrdocs_workaround_t

Remove all but the first n bytes from a buffer sequence

keep_suffix_mrdocs_workaround_t

Remove all but the last n bytes from a buffer sequence

match_delim

Match condition that searches for a delimiter string.

mutable_buffer

A reference to a contiguous region of writable memory.

mutable_buffer_archetype_

Archetype for MutableBufferSequence concept checking.

prefix_mrdocs_workaround_t

Return a sequence representing the first n bytes of a buffer sequence

recycling_memory_resource

remove_prefix_mrdocs_workaround_t

Remove n bytes from the beginning of a buffer sequence

remove_suffix_mrdocs_workaround_t

Remove n bytes from the end of a buffer sequence

run_async_wrapper

Wrapper returned by run_async that accepts a task for execution.

sans_prefix_mrdocs_workaround_t

Return a sequence representing all but the first n bytes of a buffer sequence

sans_suffix_mrdocs_workaround_t

Return a sequence representing all but the last n bytes of a buffer sequence

size_tag

Tag type for customizing buffer_size via tag_invoke.

slice_of

slice_of<BufferSequence>

A wrapper enabling a buffer sequence to be consumed

slice_tag

Tag type for customizing slice operations via tag_invoke.

strand

Provides serialized coroutine execution for any executor type.

suffix_mrdocs_workaround_t

Return a sequence representing the last n bytes of a buffer sequence

task

Lazy coroutine task satisfying IoRunnable.

thread_pool

A pool of threads for executing work concurrently.

work_guard

RAII guard that keeps an executor's context from completing.

buffer_type

Alias for mutable_buffer or const_buffer based on sequence type.

const_buffer_archetype

const_buffer_array

Alias for buffer_array holding const_buffer.

const_buffer_pair

A constant buffer pair

const_buffer_param

Alias for buffer_param that always uses const_buffer storage.

io_task

A task type for I/O operations yielding io_result.

mutable_buffer_archetype

mutable_buffer_array

Alias for buffer_array holding mutable_buffer.

mutable_buffer_pair

A mutable buffer pair

slice_type

Alias for the type representing a slice of T

string_dynamic_buffer

vector_dynamic_buffer

A dynamic buffer using std::vector<unsigned char>.

when_all_result_type

Compute the result type of when_all for the given task types.

+
+
+
+

Enums

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

cond

Portable error conditions for capy I/O operations.

error

Error codes for capy I/O operations.

slice_how

Constants for slice customization.

+
+
+
+

Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

buffer_length

Return the number of buffer elements in a sequence.

dynamic_buffer

dynamic_buffer overloads

get_current_frame_allocator

Return the current frame allocator for this thread.

get_recycling_memory_resource

Returns pointer to the default recycling memory resource.

get_system_context

Return the process‐wide system execution context.

make_buffer

make_buffer overloads

make_error_code

make_error_condition

make_work_guard

Create a work guard from an executor.

pull_from

pull_from overloads

push_to

push_to overloads

read

read overloads

read_until

read_until overloads

ready

ready overloads

run

run overloads

run_async

run_async overloads

set_current_frame_allocator

Set the current frame allocator for this thread.

tag_invoke

tag_invoke overloads

when_all

Execute multiple awaitables concurrently and collect their results.

when_any

when_any overloads

write

Asynchronously write the entire buffer sequence.

+
+
+
+

Variables

+
+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

begin

buffer_copy

buffer_empty

buffer_size

end

front

keep_prefix

keep_suffix

prefix

remove_prefix

remove_suffix

sans_prefix

sans_suffix

suffix

+
+
+
+

Concepts

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

BufferSink

Concept for types that consume buffer data using callee‐owned buffers.

BufferSource

Concept for types that produce buffer data asynchronously.

ConstBufferSequence

Concept for sequences of read‐only buffer regions.

DynamicBuffer

Concept for resizable buffer types with prepare/commit semantics.

DynamicBufferParam

Concept for valid DynamicBuffer parameter passing to coroutines.

ExecutionContext

Concept for types that provide a place where work is executed.

Executor

Concept for types that schedule coroutine execution.

IoAwaitable

Concept for awaitables that participate in the I/O protocol.

IoAwaitableRange

Concept for ranges of full I/O awaitables.

IoRunnable

Concept for task types that can be launched from non‐coroutine contexts.

MatchCondition

Concept for callables that detect delimiters in streamed data.

MutableBufferSequence

Concept for sequences of writable buffer regions.

ReadSource

Concept for types providing complete reads from a data source.

ReadStream

Concept for types providing awaitable read operations.

Stream

Concept for types providing both read and write operations.

WriteSink

Concept for types providing complete writes with EOF signaling.

WriteStream

Concept for types that provide awaitable write operations.

awaitable_decomposes_to

Concept for awaitables whose return type decomposes to a specific typelist.

decomposes_to

Concept for types that decompose to a specific typelist.

+
+
+
+

Deduction Guides

+
+ +++ + + + + + + + + + + + +

Name

buffer_param<BS>

strand<Ex>

+
+

Created with MrDocs

+
+
+
+
+
+ +
+
+ +
+ + diff --git a/preview/reference/boost/capy/BufferSink.html b/preview/reference/boost/capy/BufferSink.html new file mode 100644 index 0000000..a171510 --- /dev/null +++ b/preview/reference/boost/capy/BufferSink.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + + + boost::capy::BufferSink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::BufferSink

+
+
+
+

Concept for types that consume buffer data using callee‐owned buffers.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept BufferSink = requires(T& sink, std::span<mutable_buffer> dest, std::size_t n)
+    {
+        // Synchronous: get writable buffers from sink's internal storage
+        { sink.prepare(dest) } ‐> std::same_as<std::span<mutable_buffer>>;
+
+        // Async: commit n bytes written
+        { sink.commit(n) } ‐> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(sink.commit(n)),
+            std::error_code>;
+
+        // Async: commit n final bytes and signal end of data
+        { sink.commit_eof(n) } ‐> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(sink.commit_eof(n)),
+            std::error_code>;
+    };
+
+
+
+
+
+

Description

+
+
+

A type satisfies BufferSink if it provides a synchronous prepare member function that fills a caller‐provided span with mutable buffer descriptors pointing to the sink's internal storage, and asynchronous commit and commit_eof member functions to finalize written data.

+
+
+

This concept models the "callee owns buffers" pattern where the sink provides writable memory and the caller writes directly into it, enabling zero‐copy data transfer. Compare with WriteSink which uses the "caller owns buffers" pattern.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `T` must provide a synchronous `prepare` member function accepting a `std::span<mutable_buffer>` and returning a span of filled buffers

    +
  • +
  • +

    `T` must provide `commit(n)` returning an IoAwaitable that decomposes to `(error_code)`

    +
  • +
  • +

    `T` must provide `commit_eof(n)` returning an IoAwaitable that decomposes to `(error_code)`

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The prepare operation provides writable buffer space:

+
+
+
    +
  • +

    Returns a span of buffer descriptors that were filled

    +
  • +
  • +

    The returned buffers point to the sink's internal storage

    +
  • +
  • +

    If the returned span is empty, the sink has no available space; caller should call `commit` to flush data and try again

    +
  • +
+
+
+

The commit operation finalizes written data:

+
+
+
    +
  • +

    Commits `n` bytes written to the most recent `prepare` buffers

    +
  • +
  • +

    May trigger underlying I/O (flush to socket, compression, etc.)

    +
  • +
  • +

    On success: `ec` is `false`

    +
  • +
  • +

    On error: `ec` is `true`

    +
  • +
+
+
+

The commit_eof operation commits final data and signals end‐of‐stream:

+
+
+
    +
  • +

    Commits `n` bytes written to the most recent `prepare` buffers and finalizes the sink

    +
  • +
  • +

    After success, no further operations are permitted

    +
  • +
  • +

    On success: `ec` is `false`, sink is finalized

    +
  • +
  • +

    On error: `ec` is `true`

    +
  • +
+
+
+
+
+

Buffer Lifetime

+
+
+

Buffers returned by prepare remain valid until the next call to prepare, commit, commit_eof, or until the sink is destroyed.

+
+
+
+
+

Conforming Signatures

+
+
+
+
std::span<mutable_buffer> prepare( std::span<mutable_buffer> dest );
+
+IoAwaitable auto commit( std::size_t n );
+IoAwaitable auto commit_eof( std::size_t n );
+
+
+
+
+
+

Example

+
+
+
+
template<BufferSource Source, BufferSink Sink>
+io_task<std::size_t> transfer( Source& source, Sink& sink )
+{
+    const_buffer src_arr[16];
+    mutable_buffer dst_arr[16];
+    std::size_t total = 0;
+
+    for(;;)
+    {
+        auto [ec1, src_bufs] = co_await source.pull( src_arr );
+        if( ec1 == cond::eof )
+        {
+            auto [eof_ec] = co_await sink.commit_eof( 0 );
+            co_return {eof_ec, total};
+        }
+        if( ec1 )
+            co_return {ec1, total};
+
+        auto dst_bufs = sink.prepare( dst_arr );
+        std::size_t n = buffer_copy( dst_bufs, src_bufs );
+
+        auto [ec2] = co_await sink.commit( n );
+        if( ec2 )
+            co_return {ec2, total};
+
+        total += n;
+    }
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The sink type.

+
+
+
+

See Also

+
+
+

BufferSource, WriteSink, IoAwaitable, awaitable_decomposes_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/BufferSource.html b/preview/reference/boost/capy/BufferSource.html new file mode 100644 index 0000000..9c029f3 --- /dev/null +++ b/preview/reference/boost/capy/BufferSource.html @@ -0,0 +1,528 @@ + + + + + + + + + + + + + + boost::capy::BufferSource :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::BufferSource

+
+
+
+

Concept for types that produce buffer data asynchronously.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept BufferSource = requires(T& src, std::span<const_buffer> dest, std::size_t n)
+    {
+        { src.pull(dest) } ‐> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(src.pull(dest)),
+            std::error_code, std::span<const_buffer>>;
+        src.consume(n);
+    };
+
+
+
+
+
+

Description

+
+
+

A type satisfies BufferSource if it provides a pull member function that fills a caller‐provided span of buffer descriptors and is an IoAwaitable whose return value decomposes to (error_code,std::span<const_buffer>), plus a consume member function to indicate how many bytes were used.

+
+
+

Use this concept when you need to produce data asynchronously for transfer to a sink, such as streaming HTTP request bodies or reading file contents for transmission.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `T` must provide a `pull` member function accepting a `std::span<const_buffer>` for output

    +
  • +
  • +

    The return type must satisfy IoAwaitable

    +
  • +
  • +

    The awaitable must decompose to `(error_code,std::span<const_buffer>)` via structured bindings

    +
  • +
  • +

    `T` must provide a `consume` member function accepting a byte count

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The pull operation fills the provided buffer span with data starting from the current unconsumed position. On return, exactly one of the following is true:

+
+
+
    +
  • +

    **Data available**: `!ec` and `bufs.size() > 0`. The returned span contains buffer descriptors.

    +
  • +
  • +

    **Source exhausted**: `ec == cond::eof` and `bufs.empty()`. No more data is available; the transfer is complete.

    +
  • +
  • +

    **Error**: `ec` is `true` and `ec != cond::eof`. An error occurred.

    +
  • +
+
+
+

Calling pull multiple times without intervening consume returns the same unconsumed data. The consume operation advances the read position by the specified number of bytes. The next pull returns data starting after the consumed bytes.

+
+
+
+
+

Buffer Lifetime

+
+
+

The memory referenced by the returned buffer descriptors must remain valid until the next call to pull, consume, or until the source is destroyed.

+
+
+
+
+

Conforming Signatures

+
+
+
+
some_io_awaitable<io_result<std::span<const_buffer>>>
+pull( std::span<const_buffer> dest );
+
+void consume( std::size_t n ) noexcept;
+
+
+
+
+
+

Example

+
+
+
+
template<BufferSource Source, WriteStream Stream>
+io_task<std::size_t> transfer( Source& source, Stream& stream )
+{
+    const_buffer arr[16];
+    std::size_t total = 0;
+    for(;;)
+    {
+        auto [ec, bufs] = co_await source.pull( arr );
+        if( ec == cond::eof )
+            co_return {{}, total};
+        if( ec )
+            co_return {ec, total};
+        auto [write_ec, n] = co_await stream.write_some( bufs );
+        if( write_ec )
+            co_return {write_ec, total};
+        source.consume( n );
+        total += n;
+    }
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The source type.

+
+
+
+

See Also

+
+
+

IoAwaitable, WriteSink, awaitable_decomposes_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ConstBufferSequence.html b/preview/reference/boost/capy/ConstBufferSequence.html new file mode 100644 index 0000000..232b682 --- /dev/null +++ b/preview/reference/boost/capy/ConstBufferSequence.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + boost::capy::ConstBufferSequence :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ConstBufferSequence

+
+
+
+

Concept for sequences of read‐only buffer regions.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<typename T>
+concept ConstBufferSequence = std::is_convertible_v<T, const_buffer> || (
+        std::ranges::bidirectional_range<T> &&
+        std::is_convertible_v<std::ranges::range_value_t<T>, const_buffer>);
+
+
+
+
+
+

Description

+
+
+

A type satisfies ConstBufferSequence if it represents one or more contiguous memory regions that can be read. This includes single buffers (convertible to const_buffer) and ranges of buffers.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    Convertible to `const_buffer`, OR

    +
  • +
  • +

    A bidirectional range with value type convertible to `const_buffer`

    +
  • +
+
+
+
+
+

See Also

+
+
+

const_buffer, MutableBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/DynamicBuffer.html b/preview/reference/boost/capy/DynamicBuffer.html new file mode 100644 index 0000000..6f7fabb --- /dev/null +++ b/preview/reference/boost/capy/DynamicBuffer.html @@ -0,0 +1,473 @@ + + + + + + + + + + + + + + boost::capy::DynamicBuffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

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

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/DynamicBufferParam.html b/preview/reference/boost/capy/DynamicBufferParam.html new file mode 100644 index 0000000..e197a32 --- /dev/null +++ b/preview/reference/boost/capy/DynamicBufferParam.html @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + boost::capy::DynamicBufferParam :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::DynamicBufferParam

+
+
+
+

Concept for valid DynamicBuffer parameter passing to coroutines.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class B>
+concept DynamicBufferParam = DynamicBuffer<std::remove_cvref_t<B>> &&
+    (std::is_lvalue_reference_v<B> ||
+     requires { typename std::remove_cvref_t<B>::is_dynamic_buffer_adapter; });
+
+
+
+
+
+

Description

+
+
+

This concept constrains how a DynamicBuffer type can be passed to coroutine‐based I/O functions. It allows:

+
+
+

Lvalues of any DynamicBuffer (caller manages lifetime) ‐ Rvalues only for types with is_dynamic_buffer_adapter tag

+
+
+

The distinction exists because some buffer types (like flat_dynamic_buffer) store bookkeeping internally that would be lost if passed by rvalue, while adapters (like string_buffers) update external storage directly.

+
+
+
+
+

Conforming Signatures

+
+
+

For coroutine functions, use a forwarding reference:

+
+
+
+
io_task<std::size_t>
+read( ReadSource auto& source, DynamicBufferParam auto&& buffers );
+
+
+
+

The forwarding reference is essential because the concept inspects the value category to enforce the lvalue/rvalue rules. Using the wrong reference type causes incorrect behavior:

+
+
+
+
// WRONG: lvalue ref rejects valid rvalue adapters
+void bad1( DynamicBufferParam auto& buffers );
+bad1( fb );                    // OK
+bad1( string_buffers( s ) );   // compile error, but should work
+
+// WRONG: const ref deduces non-reference, rejects non-adapters
+void bad2( DynamicBufferParam auto const& buffers );
+bad2( fb );                    // compile error, but should work
+bad2( string_buffers( s ) );   // OK (adapter only)
+
+// CORRECT: forwarding ref enables proper checking
+void good( DynamicBufferParam auto&& buffers );
+good( fb );                    // OK: lvalue
+good( string_buffers( s ) );   // OK: adapter rvalue
+good( flat_dynamic_buffer( storage ) );  // compile error: non-adapter rvalue
+
+
+
+
+
+

Adapter Types

+
+
+

Types safe to pass as rvalues define a nested tag:

+
+
+
+
class string_dynamic_buffer {
+public:
+    using is_dynamic_buffer_adapter = void;
+    // ...
+};
+
+
+
+
+
+

Example

+
+
+
+
// OK: lvalue reference
+flat_dynamic_buffer fb( storage );
+co_await read( stream, fb );
+
+// OK: adapter as rvalue, string retains data
+std::string s;
+co_await read( stream, string_dynamic_buffer( &s ) );
+
+// ERROR: non-adapter rvalue
+co_await read( stream, flat_dynamic_buffer( storage ) );  // compile error
+
+
+
+
+
+

See Also

+
+
+

DynamicBuffer

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ExecutionContext.html b/preview/reference/boost/capy/ExecutionContext.html new file mode 100644 index 0000000..a901fda --- /dev/null +++ b/preview/reference/boost/capy/ExecutionContext.html @@ -0,0 +1,498 @@ + + + + + + + + + + + + + + boost::capy::ExecutionContext :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ExecutionContext

+
+
+
+

Concept for types that provide a place where work is executed.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class X>
+concept ExecutionContext = std::derived_from<X, execution_context> &&
+    requires(X& x) {
+        typename X::executor_type;
+        requires Executor<typename X::executor_type>;
+        { x.get_executor() } noexcept ‐> std::same_as<typename X::executor_type>;
+    };
+
+
+
+
+
+

Description

+
+
+

An execution context owns the resources (threads, event loops, completion ports) needed to execute function objects. It serves as the factory for executors, which are lightweight handles used to submit work. Multiple executors may reference the same context.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `X` must be publicly derived from `execution_context`

    +
  • +
  • +

    `X::executor_type` must be a type satisfying Executor

    +
  • +
  • +

    `x.get_executor()` must return `X::executor_type` and be `noexcept`

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The execution context owns the execution environment:

+
+
+
    +
  • +

    Work submitted via any executor from this context runs on resources owned by the context

    +
  • +
  • +

    The context remains valid while any executor referencing it exists and may be used

    +
  • +
  • +

    Destroying the context destroys all unexecuted work submitted via associated executors

    +
  • +
+
+
+
+
+

Conforming Signatures

+
+
+
+
class X : public execution_context
+{
+public:
+    using executor_type = // Executor
+    executor_type get_executor() noexcept;
+};
+
+
+
+
+
+

Example

+
+
+
+
template<ExecutionContext Ctx>
+void spawn_work( Ctx& ctx )
+{
+    auto ex = ctx.get_executor();
+    ex.post( []{ } ); // work runs on ctx
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

X

The execution context type.

+
+
+
+

See Also

+
+
+

Executor, execution_context

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/Executor.html b/preview/reference/boost/capy/Executor.html new file mode 100644 index 0000000..f227045 --- /dev/null +++ b/preview/reference/boost/capy/Executor.html @@ -0,0 +1,591 @@ + + + + + + + + + + + + + + boost::capy::Executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::Executor

+
+
+
+

Concept for types that schedule coroutine execution.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class E>
+concept Executor = std::is_nothrow_copy_constructible_v<E> &&
+    std::is_nothrow_move_constructible_v<E> &&
+    requires(E& e, E const& ce, E const& ce2, std::coroutine_handle<> h) {
+        { ce == ce2 } noexcept ‐> std::convertible_to<bool>;
+        { ce.context() } noexcept;
+        requires std::is_lvalue_reference_v<decltype(ce.context())> &&
+            std::derived_from<
+                std::remove_reference_t<decltype(ce.context())>,
+                execution_context>;
+        { ce.on_work_started() } noexcept;
+        { ce.on_work_finished() } noexcept;
+
+        { ce.dispatch(h) } ‐> std::same_as<std::coroutine_handle<>>;
+        { ce.post(h) };
+    };
+
+
+
+
+
+

Description

+
+
+

An executor embodies a set of rules for determining how and where coroutines are executed. It provides operations to submit work and to track outstanding work for graceful shutdown.

+
+
+

Ordinary users writing coroutine tasks do not interact with dispatch and post directly. These operations are used by authors of coroutine machinery ‐‐ promise_type implementations, awaitables, await_transform ‐‐ to implement asynchronous algorithms such as when_all, when_any, async_mutex, channels, and similar primitives.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `E` must be nothrow copy and move constructible

    +
  • +
  • +

    `e1 == e2` must return a type convertible to `bool`, `noexcept`

    +
  • +
  • +

    `e.context()` must return an lvalue reference to a type derived from `execution_context`, `noexcept`

    +
  • +
  • +

    `e.on_work_started()` must be valid and `noexcept`

    +
  • +
  • +

    `e.on_work_finished()` must be valid and `noexcept`

    +
  • +
  • +

    `e.dispatch(h)` must return `std::coroutine_handle<>`

    +
  • +
  • +

    `e.post(h)` must be valid

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The context operation returns the owning context:

+
+
+
    +
  • +

    Returns a reference to the execution context that created this executor

    +
  • +
  • +

    The context outlives all executors created from it

    +
  • +
+
+
+

The on_work_started and on_work_finished operations track work:

+
+
+
    +
  • +

    Calls must be paired; each `on_work_started` must have a matching `on_work_finished`

    +
  • +
  • +

    The context uses this count to determine when shutdown is complete

    +
  • +
  • +

    These are not intended for direct use by callers. They are public so that work guards can invoke them. This enables user‐defined guards with additional tracking behaviors, without the library needing to grant friendship to types it cannot anticipate

    +
  • +
+
+
+

The dispatch operation returns a handle for symmetric transfer:

+
+
+

Every coroutine resumption must go through either symmetric transfer or the scheduler queue ‐‐ never through an inline resume() or dispatch() that creates a frame below the resumed coroutine.

+
+
+
    +
  • +

    If the executor determines it is safe to resume inline (e.g., already on the correct thread), returns `h` for the caller to use in symmetric transfer

    +
  • +
  • +

    Otherwise, posts the coroutine for later execution and returns `std::noop_coroutine()`

    +
  • +
  • +

    The caller is responsible for using the returned handle appropriately: returning it from `await_suspend` for symmetric transfer, or calling `.resume()` if at the event loop pump level

    +
  • +
+
+
+

A conforming implementation might look like:

+
+
+
+
std::coroutine_handle<> dispatch(
+    std::coroutine_handle<> h ) const
+{
+    if( ctx_.is_running_on_this_thread() )
+        return h;              // symmetric transfer
+    post( h );
+    return std::noop_coroutine();
+}
+
+
+
+

The post operation queues for later execution:

+
+
+
    +
  • +

    Never blocks the caller

    +
  • +
  • +

    The coroutine executes on the executor's associated context

    +
  • +
+
+
+
+
+

Executor Validity

+
+
+

An executor becomes invalid when the first call to ctx.shutdown() returns. Calling dispatch, post, on_work_started, or on_work_finished on an invalid executor is undefined behavior. Copy, comparison, and context() remain valid until the context is destroyed.

+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Safe for copy, comparison, and context().

+
+
+
+
+

Conforming Signatures

+
+
+
+
class E
+{
+public:
+    execution_context& context() const noexcept;
+
+    void on_work_started() const noexcept;
+    void on_work_finished() const noexcept;
+
+    std::coroutine_handle<> dispatch(
+        std::coroutine_handle<> h ) const;
+    void post( std::coroutine_handle<> h ) const;
+
+    bool operator==( E const& ) const noexcept;
+};
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

E

The executor type.

+
+
+
+

See Also

+
+
+

ExecutionContext, execution_context

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/IoAwaitable.html b/preview/reference/boost/capy/IoAwaitable.html new file mode 100644 index 0000000..c257a78 --- /dev/null +++ b/preview/reference/boost/capy/IoAwaitable.html @@ -0,0 +1,528 @@ + + + + + + + + + + + + + + boost::capy::IoAwaitable :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::IoAwaitable

+
+
+
+

Concept for awaitables that participate in the I/O protocol.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename A>
+concept IoAwaitable = requires(
+        A a,
+        std::coroutine_handle<> h,
+        io_env const* env)
+    {
+        a.await_suspend(h, env);
+    };
+
+
+
+
+
+

Description

+
+
+

An awaitable satisfies IoAwaitable if its await_suspend accepts an io_env, enabling scheduler affinity, cancellation, and allocator propagation. This extended signature distinguishes I/O awaitables from standard C++ awaitables that only take a coroutine handle.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `a.await_suspend(h, env)` must be a valid expression where: ‐ `h` is a `std::coroutine_handle<>` (coroutine handle) ‐ `env` is an `io_env const*`

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

When await_suspend is called:

+
+
+
    +
  • +

    The awaitable uses `env‐>executor` to schedule resumption of the coroutine when the operation completes

    +
  • +
  • +

    The awaitable should monitor `env‐>stop_token` and complete early with a cancellation error if stop is requested

    +
  • +
  • +

    The awaitable may use `env‐>allocator` for internal allocations

    +
  • +
  • +

    The awaitable must propagate `env‐>allocator` faithfully to any child coroutines it creates

    +
  • +
  • +

    The awaitable may return `std::noop_coroutine()` to indicate the operation was started asynchronously

    +
  • +
+
+
+
+
+

Lifetime

+
+
+

The io_env passed to await_suspend is guaranteed by launch functions such as run or run_async to remain valid for the lifetime of the awaitable's async operation. Awaitables that need to retain access to the environment should store it as io_env const*, never as a copy. Copying is unnecessary and wasteful because the referent is guaranteed to outlive the operation.

+
+
+
+
+

Conforming Signatures

+
+
+
+
struct A
+{
+    bool await_ready() const noexcept;
+
+    auto await_suspend(
+        std::coroutine_handle<> h,
+        io_env const* env );
+
+    T await_resume();
+};
+
+
+
+
+
+

Example

+
+
+
+
struct my_io_op
+{
+    io_env const* env_ = nullptr;
+    std::coroutine_handle<> cont_;
+
+    auto await_suspend(
+        std::coroutine_handle<> h,
+        io_env const* env )
+    {
+        env_ = env;
+        cont_ = h;
+        // Pass members by value; capturing this
+        // risks use-after-free in async callbacks
+        start_async(
+            env_->stop_token,
+            env_->executor,
+            cont_ );
+        return std::noop_coroutine();
+    }
+
+    bool await_ready() const noexcept { return false; }
+    void await_resume() {}
+};
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

A

The awaitable type.

+
+
+
+

See Also

+
+
+

IoRunnable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/IoAwaitableRange.html b/preview/reference/boost/capy/IoAwaitableRange.html new file mode 100644 index 0000000..cc09fc3 --- /dev/null +++ b/preview/reference/boost/capy/IoAwaitableRange.html @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + boost::capy::IoAwaitableRange :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::IoAwaitableRange

+
+
+
+

Concept for ranges of full I/O awaitables.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/when_any.hpp>

+
+
+
+
template<typename R>
+concept IoAwaitableRange = std::ranges::input_range<R> &&
+    std::ranges::sized_range<R> &&
+    IoAwaitable<std::ranges::range_value_t<R>>;
+
+
+
+
+
+

Description

+
+
+

A range satisfies IoAwaitableRange if it is a sized input range whose value type satisfies IoAwaitable. This enables when_any to accept any container or view of awaitables, not just std::vector.

+
+
+
+
+

Requirements

+
+
+
    +
  • +

    `R` must satisfy `std::ranges::input_range`

    +
  • +
  • +

    `R` must satisfy `std::ranges::sized_range`

    +
  • +
  • +

    `std::ranges::range_value_t<R>` must satisfy IoAwaitable

    +
  • +
+
+
+
+
+

Syntactic Requirements

+
+
+

Given r of type R:

+
+
+
    +
  • +

    `std::ranges::begin(r)` is valid

    +
  • +
  • +

    `std::ranges::end(r)` is valid

    +
  • +
  • +

    `std::ranges::size(r)` returns `std::ranges::range_size_t<R>`

    +
  • +
  • +

    `*std::ranges::begin(r)` satisfies IoAwaitable

    +
  • +
+
+
+
+
+

Example

+
+
+
+
template<IoAwaitableRange R>
+task<void> race_all(R&& awaitables) {
+    auto winner = co_await when_any(std::forward<R>(awaitables));
+    // Process winner...
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

R

The range type.

+
+
+
+

See Also

+
+
+

when_any, IoAwaitable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/IoRunnable.html b/preview/reference/boost/capy/IoRunnable.html new file mode 100644 index 0000000..9239aee --- /dev/null +++ b/preview/reference/boost/capy/IoRunnable.html @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + boost::capy::IoRunnable :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::IoRunnable

+
+
+
+

Concept for task types that can be launched from non‐coroutine contexts.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept IoRunnable = IoAwaitable<T> &&
+    requires { typename T::promise_type; } &&
+    requires(T& t, T const& ct, typename T::promise_type const& cp, typename T::promise_type& p)
+    {
+        { ct.handle() } noexcept ‐> std::same_as<std::coroutine_handle<typename T::promise_type>>;
+        { cp.exception() } noexcept ‐> std::same_as<std::exception_ptr>;
+        { t.release() } noexcept;
+        { p.set_continuation(std::coroutine_handle<>{}) } noexcept;
+        { p.set_environment(static_cast<io_env const*>(nullptr)) } noexcept;
+    } &&
+    (std::is_void_v<decltype(std::declval<T&>().await_resume())> ||
+     requires(typename T::promise_type& p) {
+         p.result();
+     });
+
+
+
+
+
+

Description

+
+
+

Extends IoAwaitable with operations needed by launch utilities (run, run_async) to start a task, transfer ownership of the coroutine frame, and retrieve results or exceptions after completion.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `T` must satisfy IoAwaitable

    +
  • +
  • +

    `T::promise_type` must be a valid type

    +
  • +
  • +

    `t.handle()` returns `std::coroutine_handle<T::promise_type>`, must be `noexcept`

    +
  • +
  • +

    `t.release()` releases ownership, must be `noexcept`

    +
  • +
  • +

    `p.exception()` returns `std::exception_ptr`, must be `noexcept`

    +
  • +
  • +

    `p.result()` returns the task result (required for non‐void tasks)

    +
  • +
  • +

    `p.set_continuation(h)` sets the continuation handle, must be `noexcept`

    +
  • +
  • +

    `p.set_environment(env)` sets the execution environment, must be `noexcept`

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The handle operation provides access to the coroutine:

+
+
+
    +
  • +

    Returns the typed coroutine handle for the task's frame

    +
  • +
  • +

    The task retains ownership; destroying the task destroys the frame

    +
  • +
+
+
+

The release operation transfers ownership:

+
+
+
    +
  • +

    After `release()`, destroying the task does not destroy the frame

    +
  • +
  • +

    The caller becomes responsible for resuming and destroying the frame

    +
  • +
+
+
+

The exception operation retrieves failure state:

+
+
+
    +
  • +

    Returns the exception stored by the promise if the coroutine completed with an unhandled exception

    +
  • +
  • +

    Returns `nullptr` if no exception was thrown

    +
  • +
+
+
+

The result operation retrieves success state (non‐void tasks):

+
+
+
    +
  • +

    Returns the value passed to `co_return`

    +
  • +
  • +

    Behavior is undefined if called when `exception()` is non‐null

    +
  • +
+
+
+

The set_continuation operation establishes the continuation:

+
+
+
    +
  • +

    Sets the coroutine handle to resume when this task reaches `final_suspend`

    +
  • +
  • +

    Used by launch functions to wire the task back to the trampoline

    +
  • +
+
+
+

The set_environment operation establishes the execution environment:

+
+
+
    +
  • +

    Sets the `io_env` pointer that propagates executor, stop token, and allocator through the coroutine chain

    +
  • +
  • +

    The pointed‐to `io_env` must outlive the coroutine

    +
  • +
+
+
+
+
+

Conforming Signatures

+
+
+
+
class T
+{
+public:
+    struct promise_type
+    {
+        std::exception_ptr exception() noexcept;
+        R result();  // non-void tasks only
+        void set_continuation(std::coroutine_handle<>) noexcept;
+        void set_environment(io_env const*) noexcept;
+    };
+
+    std::coroutine_handle<promise_type> handle() const noexcept;
+    void release() noexcept;
+};
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The task type.

+
+
+
+

See Also

+
+
+

IoAwaitable, run, run_async

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/MatchCondition.html b/preview/reference/boost/capy/MatchCondition.html new file mode 100644 index 0000000..f92c346 --- /dev/null +++ b/preview/reference/boost/capy/MatchCondition.html @@ -0,0 +1,517 @@ + + + + + + + + + + + + + + boost::capy::MatchCondition :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::MatchCondition

+
+
+
+

Concept for callables that detect delimiters in streamed data.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class F>
+concept MatchCondition = requires(F f, std::string_view data, std::size_t* hint) {
+    { f(data, hint) } ‐> std::convertible_to<std::size_t>;
+};
+
+
+
+
+
+

Description

+
+
+

A type satisfies MatchCondition if it is callable with std::string_view and a std::size_t* hint parameter, returning the position after a match or npos if not found. Used by read_until to scan accumulated data for delimiters.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `f(data, hint)` must be a valid expression where: ‐ `data` is `std::string_view` ‐ `hint` is `std::size_t*` (may be null)

    +
  • +
  • +

    The return type must be convertible to `std::size_t`

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The callable scans data for a delimiter or pattern:

+
+
+
    +
  • +

    On match: returns position after the match (bytes to consume)

    +
  • +
  • +

    On no match: returns `std::string_view::npos`

    +
  • +
+
+
+

The hint parameter enables efficient cross‐boundary searching:

+
+
+
    +
  • +

    If `hint` is null, the matcher ignores it

    +
  • +
  • +

    If `hint` is non‐null and no match is found, the matcher may write how many bytes from the end might be part of a partial match (e.g., 3 for "\r\n\r" when searching for "\r\n\r\n")

    +
  • +
  • +

    The hint allows the caller to retain only necessary bytes when the buffer must be compacted

    +
  • +
+
+
+
+
+

Conforming Signatures

+
+
+
+
std::size_t operator()( std::string_view data, std::size_t* hint ) const;
+
+
+
+
+
+

Example

+
+
+
+
    // Simple line matcher (ignores hint)
+    auto line_matcher = []( std::string_view data, std::size_t* ) {
+        auto pos = data.find( "\r\n" );
+        return pos != std::string_view::npos ? pos + 2 : pos;
+    };
+
+    // HTTP header end matcher with overlap hint
+    struct http_header_matcher
+    {
+        std::size_t operator()(
+            std::string_view data,
+            std::size_t* hint ) const noexcept
+        {
+            auto pos = data.find( "\r\n\r\n" );
+            if( pos != std::string_view::npos )
+                return pos + 4;
+            if( hint )
+hint = 3;  // "\r\n\r" might span reads
+            return std::string_view::npos;
+        }
+    };
+
+    static_assert( MatchCondition<http_header_matcher> );
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

F

The callable type.

+
+
+
+

See Also

+
+
+

read_until

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/MutableBufferSequence.html b/preview/reference/boost/capy/MutableBufferSequence.html new file mode 100644 index 0000000..b070e7b --- /dev/null +++ b/preview/reference/boost/capy/MutableBufferSequence.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + boost::capy::MutableBufferSequence :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::MutableBufferSequence

+
+
+
+

Concept for sequences of writable buffer regions.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<typename T>
+concept MutableBufferSequence = std::is_convertible_v<T, mutable_buffer> || (
+        std::ranges::bidirectional_range<T> &&
+        std::is_convertible_v<std::ranges::range_value_t<T>, mutable_buffer>);
+
+
+
+
+
+

Description

+
+
+

A type satisfies MutableBufferSequence if it represents one or more contiguous memory regions that can be written. This includes single buffers (convertible to mutable_buffer) and ranges of buffers. Every MutableBufferSequence also satisfies ConstBufferSequence.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    Convertible to `mutable_buffer`, OR

    +
  • +
  • +

    A bidirectional range with value type convertible to `mutable_buffer`

    +
  • +
+
+
+
+
+

See Also

+
+
+

mutable_buffer, ConstBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ReadSource.html b/preview/reference/boost/capy/ReadSource.html new file mode 100644 index 0000000..50448e6 --- /dev/null +++ b/preview/reference/boost/capy/ReadSource.html @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + boost::capy::ReadSource :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ReadSource

+
+
+
+

Concept for types providing complete reads from a data source.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept ReadSource = ReadStream<T> &&
+    requires(T& source, mutable_buffer_archetype buffers)
+    {
+        { source.read(buffers) } ‐> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(source.read(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+
+
+

Description

+
+
+

A type satisfies ReadSource if it satisfies ReadStream and additionally provides a read member function that accepts any MutableBufferSequence and is an IoAwaitable whose return value decomposes to (error_code, std::size_t).

+
+
+

ReadSource refines ReadStream. Every ReadSource is a ReadStream. Algorithms constrained on ReadStream accept both raw streams and sources.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `T` must satisfy ReadStream (provides `read_some`)

    +
  • +
  • +

    `T` must provide a `read` member function template accepting any MutableBufferSequence

    +
  • +
  • +

    The return type of `read` must satisfy IoAwaitable

    +
  • +
  • +

    The awaitable must decompose to `(error_code, std::size_t)` via structured bindings

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The inherited read_some operation reads one or more bytes (partial read). See ReadStream.

+
+
+

The read operation fills the entire buffer sequence. On return, exactly one of the following is true:

+
+
+
    +
  • +

    **Success**: `!ec` and `n` equals `buffer_size( buffers )`. The entire buffer sequence was filled.

    +
  • +
  • +

    **End‐of‐stream**: `ec == cond::eof` and `n` indicates the number of bytes transferred before EOF was reached.

    +
  • +
  • +

    **Error**: `ec` and `n` indicates the number of bytes transferred before the error.

    +
  • +
+
+
+

Successful partial reads are not permitted; either the entire buffer is filled or the operation returns with an error.

+
+
+

If buffer_empty( buffers ) is true, the operation completes immediately with !ec and n equal to 0.

+
+
+

When the buffer sequence contains multiple buffers, each buffer is filled completely before proceeding to the next.

+
+
+
+
+

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< MutableBufferSequence MB >
+IoAwaitable auto read_some( MB buffers );   // inherited from ReadStream
+
+template< MutableBufferSequence MB >
+IoAwaitable auto read( MB buffers );
+
+
+
+ + + + + +
+ + +
+

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< ReadSource Source >
+task<> read_header( Source& source )
+{
+    char header[16];
+    auto [ec, n] = co_await source.read(
+        mutable_buffer( header ) );
+    if( ec )
+        co_return;
+    // header contains exactly 16 bytes
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The source type.

+
+
+
+

See Also

+
+
+

ReadStream, IoAwaitable, MutableBufferSequence, awaitable_decomposes_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ReadStream.html b/preview/reference/boost/capy/ReadStream.html new file mode 100644 index 0000000..5a3e2c7 --- /dev/null +++ b/preview/reference/boost/capy/ReadStream.html @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + boost::capy::ReadStream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ReadStream

+
+
+
+

Concept for types providing awaitable read operations.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept ReadStream = requires(T& stream, mutable_buffer_archetype buffers)
+    {
+        { stream.read_some(buffers) } ‐> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(stream.read_some(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+
+
+

Description

+
+
+

A type satisfies ReadStream if it provides a read_some member function template that accepts any MutableBufferSequence and is an IoAwaitable yielding (error_code,std::size_t).

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `T` must provide a `read_some` member function template accepting any MutableBufferSequence

    +
  • +
  • +

    The return type of `read_some` must satisfy IoAwaitable

    +
  • +
  • +

    The awaitable's result must decompose to `(error_code,std::size_t)` via structured bindings

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

If buffer_size( buffers ) > 0, the operation reads one or more bytes from the stream into the buffer sequence:

+
+
+
    +
  • +

    On success: `!ec`, and `n` is the number of bytes read (at least 1).

    +
  • +
  • +

    On error: `ec`, and `n` is 0.

    +
  • +
  • +

    On end‐of‐file: `ec == cond::eof`, and `n` is 0.

    +
  • +
+
+
+

If buffer_empty( buffers ) is true, the operation completes immediately. !ec, and n is 0.

+
+
+

Buffers in the sequence are filled completely before proceeding to the next buffer.

+
+
+
+
+

Design Rationale

+
+
+

The requirement that n is 0 whenever ec is set follows from a consistency constraint with the empty‐buffer rule. See the ReadStream design document for a complete derivation.

+
+
+
+
+

Buffer Lifetime

+
+
+

The caller must ensure that the memory referenced by buffers remains valid until the co_await expression returns.

+
+
+
+
+

Conforming Signatures

+
+
+
+
// Templated for any MutableBufferSequence
+template< MutableBufferSequence MB >
+IoAwaitable auto read_some( MB const& buffers );
+
+template< MutableBufferSequence MB >
+IoAwaitable auto read_some( MB buffers );  // by-value also permitted
+
+
+
+ + + + + +
+ + +
+

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< ReadStream Stream >
+task<> read_all( Stream& s, char* buf, std::size_t size )
+{
+    std::size_t total = 0;
+    while( total < size )
+    {
+        auto [ec, n] = co_await s.read_some(
+            mutable_buffer( buf + total, size - total ) );
+        if( ec )
+            co_return;
+        total += n;
+    }
+}
+
+
+
+
+
+

See Also

+
+
+

IoAwaitable, MutableBufferSequence, awaitable_decomposes_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/Stream.html b/preview/reference/boost/capy/Stream.html new file mode 100644 index 0000000..058d36f --- /dev/null +++ b/preview/reference/boost/capy/Stream.html @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + boost::capy::Stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::Stream

+
+
+
+

Concept for types providing both read and write operations.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept Stream = ReadStream<T> && WriteStream<T>;
+
+
+
+
+
+

Description

+
+
+

A type satisfies Stream if it satisfies both ReadStream and WriteStream.

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    Must satisfy ReadStream

    +
  • +
  • +

    Must satisfy WriteStream

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

The semantics are the union of ReadStream and WriteStream. The stream supports bidirectional I/O through read_some and write_some operations.

+
+
+
+
+

Example

+
+
+
+
template<Stream S>
+task<> echo(S& stream)
+{
+    char buf[1024];
+    auto [ec, n] = co_await stream.read_some(mutable_buffer(buf));
+    if(ec)
+        co_return;
+    co_await stream.write_some(const_buffer(buf, n));
+}
+
+
+
+
+
+

See Also

+
+
+

ReadStream, WriteStream

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/WriteSink.html b/preview/reference/boost/capy/WriteSink.html new file mode 100644 index 0000000..bd7ef82 --- /dev/null +++ b/preview/reference/boost/capy/WriteSink.html @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + boost::capy::WriteSink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

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();
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The sink type.

+
+
+
+

See Also

+
+
+

WriteStream, IoAwaitable, ConstBufferSequence, awaitable_decomposes_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/WriteStream.html b/preview/reference/boost/capy/WriteStream.html new file mode 100644 index 0000000..f9d915b --- /dev/null +++ b/preview/reference/boost/capy/WriteStream.html @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + boost::capy::WriteStream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::WriteStream

+
+
+
+

Concept for types that provide awaitable write operations.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+concept WriteStream = requires(T& stream, const_buffer_archetype buffers)
+    {
+        { stream.write_some(buffers) } ‐> IoAwaitable;
+        requires awaitable_decomposes_to<
+            decltype(stream.write_some(buffers)),
+            std::error_code, std::size_t>;
+    };
+
+
+
+
+
+

Description

+
+
+

A type satisfies WriteStream if it provides a write_some member function template that accepts any ConstBufferSequence and is an IoAwaitable whose return value decomposes to (error_code,std::size_t).

+
+
+
+
+

Syntactic Requirements

+
+
+
    +
  • +

    `T` must provide a `write_some` member function template accepting any ConstBufferSequence

    +
  • +
  • +

    The return type of `write_some` must satisfy IoAwaitable

    +
  • +
  • +

    The awaitable's result must decompose to `(error_code,std::size_t)` via structured bindings

    +
  • +
+
+
+
+
+

Semantic Requirements

+
+
+

If buffer_size( buffers ) > 0, the operation writes one or more bytes of data to the stream from the buffer sequence:

+
+
+
    +
  • +

    On success: `!ec`, and `n` is the number of bytes written.

    +
  • +
  • +

    On error: `ec`, and `n` is 0.

    +
  • +
+
+
+

If buffer_empty( buffers ) is true, the operation completes immediately. !ec, and n is 0.

+
+
+

Buffers in the sequence are written completely before proceeding to the next buffer.

+
+
+
+
+

Buffer Lifetime

+
+
+

The caller must ensure that the memory referenced by buffers remains valid until the co_await expression returns.

+
+
+
+
+

Conforming Signatures

+
+
+
+
template< ConstBufferSequence Buffers >
+IoAwaitable auto write_some( Buffers buffers );
+
+
+
+ + + + + +
+ + +
+

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< WriteStream Stream >
+task<> write_all( Stream& s, char const* buf, std::size_t size )
+{
+    std::size_t total = 0;
+    while( total < size )
+    {
+        auto [ec, n] = co_await s.write_some(
+            const_buffer( buf + total, size - total ) );
+        if( ec )
+            co_return;
+        total += n;
+    }
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The stream type.

+
+
+
+

See Also

+
+
+

IoAwaitable, ConstBufferSequence, awaitable_decomposes_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink.html b/preview/reference/boost/capy/any_buffer_sink.html new file mode 100644 index 0000000..7d3a9ab --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink.html @@ -0,0 +1,553 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink

+
+
+
+

Type‐erased wrapper for any BufferSink.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_buffer_sink;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying the BufferSink concept, enabling runtime polymorphism for buffer sink operations. It uses cached awaitable storage to achieve zero steady‐state allocation after construction.

+
+
+

The wrapper exposes two interfaces for producing data: the BufferSink interface (prepare, commit, commit_eof) and the WriteSink interface (write_some, write, write_eof). Choose the interface that matches how your data is produced:

+
+
+
+
+

Choosing an Interface

+
+
+

Use the BufferSink interface when you are a generator that produces data into externally‐provided buffers. The sink owns the memory; you call prepare to obtain writable buffers, fill them, then call commit or commit_eof.

+
+
+

Use the WriteSink interface when you already have buffers containing the data to write: ‐ If the entire body is available up front, call write_eof(buffers) to send everything atomically. ‐ If data arrives incrementally, call write or write_some in a loop, then write_eof() when done. Prefer write (complete) unless your streaming pattern benefits from partial writes via write_some.

+
+
+

If the wrapped type only satisfies BufferSink, the WriteSink operations are provided automatically.

+
+
+
+
+

Construction Modes

+
+
+

Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the sink. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to sink must outlive this wrapper.

+
+
+
+
+

Awaitable Preallocation

+
+
+

The constructor preallocates storage for the type‐erased awaitable. This reserves all virtual address space at server startup so memory usage can be measured up front, rather than allocating piecemeal as traffic arrives.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations on the same wrapper are undefined behavior.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the sink
+any_buffer_sink abs(some_buffer_sink{args...});
+
+// Reference - wraps without ownership
+some_buffer_sink sink;
+any_buffer_sink abs(&sink);
+
+// BufferSink interface: generate into callee-owned buffers
+mutable_buffer arr[16];
+auto bufs = abs.prepare(arr);
+// Write data into bufs[0..bufs.size())
+auto [ec] = co_await abs.commit(bytes_written);
+auto [ec2] = co_await abs.commit_eof(0);
+
+// WriteSink interface: send caller-owned buffers
+auto [ec3, n] = co_await abs.write(make_buffer("hello", 5));
+auto [ec4] = co_await abs.write_eof();
+
+// Or send everything at once
+auto [ec5, n2] = co_await abs.write_eof(
+    make_buffer(body_data));
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_buffer_sink [constructor]

Constructors

~any_buffer_sink [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

commit

Commit bytes written to the prepared buffers.

commit_eof

Commit final bytes and signal end‐of‐stream.

has_value

Check if the wrapper contains a valid sink.

prepare

Prepare writable buffers.

write

Write all data from a buffer sequence.

write_eof

write_eof overloads

write_some

Write some data from a buffer sequence.

operator bool

Check if the wrapper contains a valid sink.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new sink after move.

+
+
+
+

See Also

+
+
+

any_buffer_source, BufferSink, WriteSink

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2constructor-06.html b/preview/reference/boost/capy/any_buffer_sink/2constructor-06.html new file mode 100644 index 0000000..6f93958 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2constructor-06.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::any_buffer_sink

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_buffer_sink() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_buffer_sink(any_buffer_sink const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_buffer_sink(any_buffer_sink&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a BufferSink.

+
+
+
+
template<BufferSink S>
+requires (!std::same_as<std::decay_t<S>, any_buffer_sink>)
+any_buffer_sink(S s);
+
+
+ +
+

Construct by wrapping a BufferSink without ownership.

+
+
+
+
template<BufferSink S>
+any_buffer_sink(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The sink to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2constructor-07a.html b/preview/reference/boost/capy/any_buffer_sink/2constructor-07a.html new file mode 100644 index 0000000..e81037a --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2constructor-07a.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::any_buffer_sink

+
+
+
+

Non‐copyable.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_sink(any_buffer_sink const& other) = delete;
+
+
+
+
+
+

Description

+
+
+

The awaitable cache is per‐instance and cannot be shared.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2constructor-07d.html b/preview/reference/boost/capy/any_buffer_sink/2constructor-07d.html new file mode 100644 index 0000000..69ac36a --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2constructor-07d.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::any_buffer_sink

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_sink(any_buffer_sink&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers ownership of the wrapped sink (if owned) and cached awaitable storage from other. After the move, other is in a default‐constructed state.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2constructor-08.html b/preview/reference/boost/capy/any_buffer_sink/2constructor-08.html new file mode 100644 index 0000000..50cc40d --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2constructor-08.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::any_buffer_sink

+
+
+
+

Construct by taking ownership of a BufferSink.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<BufferSink S>
+requires (!std::same_as<std::decay_t<S>, any_buffer_sink>)
+any_buffer_sink(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the sink into this wrapper. The wrapper owns the sink and will destroy it. If S also satisfies WriteSink, native write operations are forwarded through the virtual boundary.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The sink to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2constructor-0c9.html b/preview/reference/boost/capy/any_buffer_sink/2constructor-0c9.html new file mode 100644 index 0000000..2a253e6 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2constructor-0c9.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::any_buffer_sink

+
+
+
+

Construct by wrapping a BufferSink without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<BufferSink S>
+any_buffer_sink(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given sink by pointer. The sink must remain valid for the lifetime of this wrapper. If S also satisfies WriteSink, native write operations are forwarded through the virtual boundary.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the sink to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2constructor-0ca.html b/preview/reference/boost/capy/any_buffer_sink/2constructor-0ca.html new file mode 100644 index 0000000..53ae5ed --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2constructor-0ca.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2conversion.html b/preview/reference/boost/capy/any_buffer_sink/2conversion.html new file mode 100644 index 0000000..8109240 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/2destructor.html b/preview/reference/boost/capy/any_buffer_sink/2destructor.html new file mode 100644 index 0000000..31fa699 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::~any_buffer_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/commit.html b/preview/reference/boost/capy/any_buffer_sink/commit.html new file mode 100644 index 0000000..68789a1 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/commit.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::commit :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::commit

+
+
+
+

Commit bytes written to the prepared buffers.

+
+
+
+
+

Synopsis

+
+ +
+
+
auto
+commit(std::size_t n);
+
+
+
+
+
+

Description

+
+
+

Commits n bytes written to the buffers returned by the most recent call to prepare. The operation may trigger underlying I/O.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to commit.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/commit_eof.html b/preview/reference/boost/capy/any_buffer_sink/commit_eof.html new file mode 100644 index 0000000..9212daa --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/commit_eof.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::commit_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::commit_eof

+
+
+
+

Commit final bytes and signal end‐of‐stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
auto
+commit_eof(std::size_t n);
+
+
+
+
+
+

Description

+
+
+

Commits n bytes written to the buffers returned by the most recent call to prepare and finalizes the sink. After success, no further operations are permitted.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to commit.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/has_value.html b/preview/reference/boost/capy/any_buffer_sink/has_value.html new file mode 100644 index 0000000..38065dc --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/has_value.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/operator_assign-02.html b/preview/reference/boost/capy/any_buffer_sink/operator_assign-02.html new file mode 100644 index 0000000..0aceadf --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/operator_assign-02.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_buffer_sink&
+operator=(any_buffer_sink const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+
+
any_buffer_sink&
+operator=(any_buffer_sink&& other) noexcept;
+
+
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/operator_assign-07.html b/preview/reference/boost/capy/any_buffer_sink/operator_assign-07.html new file mode 100644 index 0000000..43f7956 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/operator_assign-07.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_sink&
+operator=(any_buffer_sink&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned sink and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/operator_assign-0d.html b/preview/reference/boost/capy/any_buffer_sink/operator_assign-0d.html new file mode 100644 index 0000000..44b9b5d --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/operator_assign-0d.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_sink&
+operator=(any_buffer_sink const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/prepare.html b/preview/reference/boost/capy/any_buffer_sink/prepare.html new file mode 100644 index 0000000..26de52f --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/prepare.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::prepare :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::prepare

+
+
+
+

Prepare writable buffers.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::span<mutable_buffer>
+prepare(std::span<mutable_buffer> dest);
+
+
+
+
+
+

Description

+
+
+

Fills the provided span with mutable buffer descriptors pointing to the underlying sink's internal storage. This operation is synchronous.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

A span of filled buffers.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

dest

Span of mutable_buffer to fill.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/rebind.html b/preview/reference/boost/capy/any_buffer_sink/rebind.html new file mode 100644 index 0000000..9bfb00b --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/rebind.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::rebind :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::rebind

+
+
+
+

Rebind to a new sink after move.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<BufferSink S>
+void
+rebind(S& new_sink) noexcept;
+
+
+
+
+
+

Description

+
+
+

Updates the internal pointer to reference a new sink object. Used by owning wrappers after move assignment when the owned object has moved to a new location.

+
+
+ + + + + +
+ + +
+

Terminates if called with a sink of different type than the original.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

new_sink

The new sink to bind to. Must be the same type as the original sink.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/write.html b/preview/reference/boost/capy/any_buffer_sink/write.html new file mode 100644 index 0000000..2a12a5f --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/write.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::write :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::write

+
+
+
+

Write all data from a buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes all data from the buffer sequence to the underlying sink. This method satisfies the WriteSink concept.

+
+
+

When the wrapped type provides native WriteSink support, each window is forwarded directly. Otherwise the data is copied into the sink via prepare and commit.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/write_eof-08.html b/preview/reference/boost/capy/any_buffer_sink/write_eof-08.html new file mode 100644 index 0000000..f830ad7 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/write_eof-08.html @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::write_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::write_eof

+
+
+
+

write_eof overloads

+
+
+
+
+

Synopses

+
+ +
+

Signal end‐of‐stream.

+
+
+
+
auto
+write_eof();
+
+
+ +
+

Atomically write data and signal end‐of‐stream.

+
+
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write_eof(CB buffers);
+
+
+ +
+
+
+

Return Value

+
+
+
    +
  • +

    An awaitable yielding (error_code).

    +
  • +
  • +

    An awaitable yielding (error_code,std::size_t).

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/write_eof-0b.html b/preview/reference/boost/capy/any_buffer_sink/write_eof-0b.html new file mode 100644 index 0000000..02c4a53 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/write_eof-0b.html @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::write_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::write_eof

+
+
+
+

Signal end‐of‐stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
auto
+write_eof();
+
+
+
+
+
+

Description

+
+
+

Indicates that no more data will be written to the sink. This method satisfies the WriteSink concept.

+
+
+

When the wrapped type provides native WriteSink support, the underlying write_eof() is called. Otherwise the operation is implemented as commit_eof(0).

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code).

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/write_eof-0e.html b/preview/reference/boost/capy/any_buffer_sink/write_eof-0e.html new file mode 100644 index 0000000..abb0c91 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/write_eof-0e.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::write_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::write_eof

+
+
+
+

Atomically write data and signal end‐of‐stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write_eof(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes all data from the buffer sequence to the underlying sink and then signals end‐of‐stream.

+
+
+

When the wrapped type provides native WriteSink support, the final window is sent atomically via the underlying write_eof(buffers). Otherwise the data is synthesized through prepare, commit, and commit_eof.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_sink/write_some.html b/preview/reference/boost/capy/any_buffer_sink/write_some.html new file mode 100644 index 0000000..09c6f9b --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_sink/write_some.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_sink::write_some :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_sink::write_some

+
+
+
+

Write some data from a buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write_some(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes one or more bytes from the buffer sequence to the underlying sink. May consume less than the full sequence.

+
+
+

When the wrapped type provides native WriteSink support, the operation forwards directly. Otherwise it is synthesized from prepare and commit with a buffer copy.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source.html b/preview/reference/boost/capy/any_buffer_source.html new file mode 100644 index 0000000..1f26b79 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source.html @@ -0,0 +1,521 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source

+
+
+
+

Type‐erased wrapper for any BufferSource.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_buffer_source;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying the BufferSource concept, enabling runtime polymorphism for buffer pull operations. It uses cached awaitable storage to achieve zero steady‐state allocation after construction.

+
+
+

The wrapper also satisfies ReadSource. When the wrapped type satisfies only BufferSource, the read operations are synthesized using pull and consume with an extra buffer copy. When the wrapped type satisfies both BufferSource and ReadSource, the native read operations are forwarded directly across the virtual boundary, avoiding the copy.

+
+
+

The wrapper supports two construction modes: ‐ Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the source. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to source must outlive this wrapper.

+
+
+

Within each mode, the vtable is populated at compile time based on whether the wrapped type also satisfies ReadSource: ‐ BufferSource only: read_some and read are synthesized from pull and consume, incurring one buffer copy per operation. ‐ BufferSource + ReadSource: All read operations are forwarded natively through the type‐erased boundary with no extra copy.

+
+
+
+
+

Awaitable Preallocation

+
+
+

The constructor preallocates storage for the type‐erased awaitable. This reserves all virtual address space at server startup so memory usage can be measured up front, rather than allocating piecemeal as traffic arrives.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations on the same wrapper are undefined behavior.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the source
+any_buffer_source abs(some_buffer_source{args...});
+
+// Reference - wraps without ownership
+some_buffer_source src;
+any_buffer_source abs(&src);
+
+const_buffer arr[16];
+auto [ec, bufs] = co_await abs.pull(arr);
+
+// ReadSource interface also available
+char buf[64];
+auto [ec2, n] = co_await abs.read_some(mutable_buffer(buf, 64));
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_buffer_source [constructor]

Constructors

~any_buffer_source [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

consume

Consume bytes from the source.

has_value

Check if the wrapper contains a valid source.

pull

Pull buffer data from the source.

read

Read data into a mutable buffer sequence.

read_some

Read some data into a mutable buffer sequence.

operator bool

Check if the wrapper contains a valid source.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new source after move.

+
+
+
+

See Also

+
+
+

any_buffer_sink, BufferSource, ReadSource

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2constructor-02.html b/preview/reference/boost/capy/any_buffer_source/2constructor-02.html new file mode 100644 index 0000000..a5ba370 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2constructor-02.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2constructor-03.html b/preview/reference/boost/capy/any_buffer_source/2constructor-03.html new file mode 100644 index 0000000..fb5ee8b --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2constructor-03.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::any_buffer_source

+
+
+
+

Construct by wrapping a BufferSource without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<BufferSource S>
+any_buffer_source(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given source by pointer. The source must remain valid for the lifetime of this wrapper. If S also satisfies ReadSource, native read operations are forwarded through the virtual boundary.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the source to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2constructor-04.html b/preview/reference/boost/capy/any_buffer_source/2constructor-04.html new file mode 100644 index 0000000..9b94c3b --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2constructor-04.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::any_buffer_source

+
+
+
+

Non‐copyable.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_source(any_buffer_source const& other) = delete;
+
+
+
+
+
+

Description

+
+
+

The awaitable cache is per‐instance and cannot be shared.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2constructor-07.html b/preview/reference/boost/capy/any_buffer_source/2constructor-07.html new file mode 100644 index 0000000..7dc40c2 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2constructor-07.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::any_buffer_source

+
+
+
+

Construct by taking ownership of a BufferSource.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<BufferSource S>
+requires (!std::same_as<std::decay_t<S>, any_buffer_source>)
+any_buffer_source(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the source into this wrapper. The wrapper owns the source and will destroy it. If S also satisfies ReadSource, native read operations are forwarded through the virtual boundary.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The source to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2constructor-08.html b/preview/reference/boost/capy/any_buffer_source/2constructor-08.html new file mode 100644 index 0000000..04897f6 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2constructor-08.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::any_buffer_source

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_source(any_buffer_source&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers ownership of the wrapped source (if owned) and cached awaitable storage from other. After the move, other is in a default‐constructed state.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2constructor-0c.html b/preview/reference/boost/capy/any_buffer_source/2constructor-0c.html new file mode 100644 index 0000000..dcc785f --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2constructor-0c.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::any_buffer_source

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_buffer_source() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_buffer_source(any_buffer_source const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_buffer_source(any_buffer_source&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a BufferSource.

+
+
+
+
template<BufferSource S>
+requires (!std::same_as<std::decay_t<S>, any_buffer_source>)
+any_buffer_source(S s);
+
+
+ +
+

Construct by wrapping a BufferSource without ownership.

+
+
+
+
template<BufferSource S>
+any_buffer_source(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The source to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2conversion.html b/preview/reference/boost/capy/any_buffer_source/2conversion.html new file mode 100644 index 0000000..20cdcc3 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/2destructor.html b/preview/reference/boost/capy/any_buffer_source/2destructor.html new file mode 100644 index 0000000..875562a --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::~any_buffer_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/consume.html b/preview/reference/boost/capy/any_buffer_source/consume.html new file mode 100644 index 0000000..4330dd5 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/consume.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::consume

+
+
+
+

Consume bytes from the source.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+consume(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Advances the internal read position of the underlying source by the specified number of bytes. The next call to pull returns data starting after the consumed bytes.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid source (has_value() == true).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to consume. Must not exceed the total size of buffers returned by the previous pull.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/has_value.html b/preview/reference/boost/capy/any_buffer_source/has_value.html new file mode 100644 index 0000000..82b85d5 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/has_value.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/operator_assign-02.html b/preview/reference/boost/capy/any_buffer_source/operator_assign-02.html new file mode 100644 index 0000000..4de251d --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/operator_assign-02.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_source&
+operator=(any_buffer_source const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/operator_assign-08.html b/preview/reference/boost/capy/any_buffer_source/operator_assign-08.html new file mode 100644 index 0000000..3e28812 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/operator_assign-08.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_buffer_source&
+operator=(any_buffer_source const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+ +
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/operator_assign-0d.html b/preview/reference/boost/capy/any_buffer_source/operator_assign-0d.html new file mode 100644 index 0000000..b4e6944 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/operator_assign-0d.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_buffer_source&
+operator=(any_buffer_source&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned source and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/pull.html b/preview/reference/boost/capy/any_buffer_source/pull.html new file mode 100644 index 0000000..f860c28 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/pull.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::pull :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::pull

+
+
+
+

Pull buffer data from the source.

+
+
+
+
+

Synopsis

+
+ +
+
+
auto
+pull(std::span<const_buffer> dest);
+
+
+
+
+
+

Description

+
+
+

Fills the provided span with buffer descriptors from the underlying source. The operation completes when data is available, the source is exhausted, or an error occurs.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid source (has_value() == true). The caller must not call this function again after a prior call returned an error.

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::span<const_buffer>). On success with data, a non‐empty span of filled buffers. On EOF, ec == cond::eof and span is empty.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

dest

Span of const_buffer to fill.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/read.html b/preview/reference/boost/capy/any_buffer_source/read.html new file mode 100644 index 0000000..a13490d --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/read.html @@ -0,0 +1,441 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::read :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::read

+
+
+
+

Read data into a mutable buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<MutableBufferSequence MB>
+io_task<std::size_t>
+read(MB buffers);
+
+
+
+
+
+

Description

+
+
+

Fills the provided buffer sequence completely. When the wrapped type provides native ReadSource support, each window is forwarded directly. Otherwise the data is synthesized from pull, buffer_copy, and consume.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid source (has_value() == true). The caller must not call this function again after a prior call returned an error (including EOF).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t). On success, n == buffer_size(buffers). On EOF, ec == error::eof and n is bytes transferred.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to fill.

+
+
+
+

See Also

+
+
+

pull, consume

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/read_some.html b/preview/reference/boost/capy/any_buffer_source/read_some.html new file mode 100644 index 0000000..985c135 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/read_some.html @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::read_some :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::read_some

+
+
+
+

Read some data into a mutable buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<MutableBufferSequence MB>
+io_task<std::size_t>
+read_some(MB buffers);
+
+
+
+
+
+

Description

+
+
+

Reads one or more bytes into the caller's buffers. May fill less than the full sequence.

+
+
+

When the wrapped type provides native ReadSource support, the operation forwards directly. Otherwise it is synthesized from pull, buffer_copy, and consume.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid source (has_value() == true). The caller must not call this function again after a prior call returned an error (including EOF).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to fill.

+
+
+
+

See Also

+
+
+

pull, consume

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_buffer_source/rebind.html b/preview/reference/boost/capy/any_buffer_source/rebind.html new file mode 100644 index 0000000..4aba0d4 --- /dev/null +++ b/preview/reference/boost/capy/any_buffer_source/rebind.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::any_buffer_source::rebind :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_buffer_source::rebind

+
+
+
+

Rebind to a new source after move.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<BufferSource S>
+void
+rebind(S& new_source) noexcept;
+
+
+
+
+
+

Description

+
+
+

Updates the internal pointer to reference a new source object. Used by owning wrappers after move assignment when the owned object has moved to a new location.

+
+
+ + + + + +
+ + +
+

Terminates if called with a source of different type than the original.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

new_source

The new source to bind to. Must be the same type as the original source.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor.html b/preview/reference/boost/capy/any_executor.html new file mode 100644 index 0000000..9cb57c7 --- /dev/null +++ b/preview/reference/boost/capy/any_executor.html @@ -0,0 +1,504 @@ + + + + + + + + + + + + + + boost::capy::any_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor

+
+
+
+

A type‐erased wrapper for executor objects.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_executor;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any executor type, enabling runtime polymorphism with automatic memory management via shared ownership. It stores a shared pointer to a polymorphic wrapper, allowing executors of different types to be stored uniformly while satisfying the full Executor concept.

+
+
+
+
+

Value Semantics

+
+
+

This class has value semantics with shared ownership. Copy and move operations are cheap, simply copying the internal shared pointer. Multiple any_executor instances may share the same underlying executor. Move operations do not invalidate the source; there is no moved‐from state.

+
+
+
+
+

Default State

+
+
+

A default‐constructed any_executor holds no executor. Calling executor operations on a default‐constructed instance results in undefined behavior. Use operator bool() to check validity.

+
+
+
+
+

Thread Safety

+
+
+

The any_executor itself is thread‐safe for concurrent reads. Concurrent modification requires external synchronization. Executor operations are safe to call concurrently if the underlying executor supports it.

+
+
+
+
+

Executor Concept

+
+
+

This class satisfies the Executor concept, making it usable anywhere a concrete executor is expected.

+
+
+
+
+

Example

+
+
+
+
any_executor exec = ctx.get_executor();
+if(exec)
+{
+    auto& context = exec.context();
+    exec.post(my_coroutine);
+}
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_executor [constructor]

Constructors

operator=

Copy assignment operator.

context

Returns a reference to the associated execution context.

dispatch

Dispatches a coroutine handle through the wrapped executor.

on_work_finished

Informs the executor that work has completed.

on_work_started

Informs the executor that work is beginning.

post

Posts a coroutine handle to the wrapped executor.

target_type

Returns the type_info of the wrapped executor.

operator bool

Returns true if this instance holds a valid executor.

operator==

Compares two executor wrappers for equality.

+
+
+
+

See Also

+
+
+

executor_ref, Executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/2constructor-05.html b/preview/reference/boost/capy/any_executor/2constructor-05.html new file mode 100644 index 0000000..387698f --- /dev/null +++ b/preview/reference/boost/capy/any_executor/2constructor-05.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::any_executor::any_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::any_executor

+
+
+
+

Constructs from any executor type.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class Ex>
+requires (
+            !std::same_as<std::decay_t<Ex>, any_executor> &&
+            !detail::is_strand_type<std::decay_t<Ex>>::value &&
+            std::copy_constructible<std::decay_t<Ex>>)
+any_executor(Ex&& ex);
+
+
+
+
+
+

Description

+
+
+

Allocates storage for a copy of the given executor and stores it internally. The executor must satisfy the Executor concept.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `*this` is valid

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The executor to wrap. A copy is stored internally.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/2constructor-0d6.html b/preview/reference/boost/capy/any_executor/2constructor-0d6.html new file mode 100644 index 0000000..1f6f26e --- /dev/null +++ b/preview/reference/boost/capy/any_executor/2constructor-0d6.html @@ -0,0 +1,441 @@ + + + + + + + + + + + + + + boost::capy::any_executor::any_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::any_executor

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_executor() = default;
+
+
+ +
+

Copy constructor.

+
+
+
+
any_executor(any_executor const& other) = default;
+
+
+ +
+

Constructs from any executor type.

+
+
+
+
template<class Ex>
+requires (
+            !std::same_as<std::decay_t<Ex>, any_executor> &&
+            !detail::is_strand_type<std::decay_t<Ex>>::value &&
+            std::copy_constructible<std::decay_t<Ex>>)
+any_executor(Ex&& ex);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The executor to wrap. A copy is stored internally.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/2constructor-0d7.html b/preview/reference/boost/capy/any_executor/2constructor-0d7.html new file mode 100644 index 0000000..baf0db7 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/2constructor-0d7.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::any_executor::any_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::any_executor

+
+
+
+

Default constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+any_executor() = default;
+
+
+
+
+
+

Description

+
+
+

Constructs an empty any_executor. Calling any executor operations on a default‐constructed instance results in undefined behavior.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `!*this`

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/2constructor-0f.html b/preview/reference/boost/capy/any_executor/2constructor-0f.html new file mode 100644 index 0000000..6766fd5 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/2constructor-0f.html @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + boost::capy::any_executor::any_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::any_executor

+
+
+
+

Copy constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_executor(any_executor const& other) = default;
+
+
+
+
+
+

Description

+
+
+

Creates a new any_executor sharing ownership of the underlying executor with other.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `*this == other`

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/2conversion.html b/preview/reference/boost/capy/any_executor/2conversion.html new file mode 100644 index 0000000..dcde2f9 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_executor::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/context.html b/preview/reference/boost/capy/any_executor/context.html new file mode 100644 index 0000000..937b2a2 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/context.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::any_executor::context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/dispatch.html b/preview/reference/boost/capy/any_executor/dispatch.html new file mode 100644 index 0000000..a7b7df4 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/dispatch.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::any_executor::dispatch :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::dispatch

+
+
+
+

Dispatches a coroutine handle through the wrapped executor.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+dispatch(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

Returns a handle for symmetric transfer. If running in the executor's thread, returns h. Otherwise, posts the coroutine for later execution and returns std::noop_coroutine().

+
+
+
+
+

Return Value

+
+
+

A handle for symmetric transfer or std::noop_coroutine().

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to dispatch for resumption.

+
+
+
+

Preconditions

+
+
+
    +
  • +

    This instance holds a valid executor.

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/on_work_finished.html b/preview/reference/boost/capy/any_executor/on_work_finished.html new file mode 100644 index 0000000..53d726b --- /dev/null +++ b/preview/reference/boost/capy/any_executor/on_work_finished.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::any_executor::on_work_finished :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/on_work_started.html b/preview/reference/boost/capy/any_executor/on_work_started.html new file mode 100644 index 0000000..d22f985 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/on_work_started.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::any_executor::on_work_started :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::on_work_started

+
+
+
+

Informs the executor that work is beginning.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+on_work_started() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Must be paired with a subsequent call to on_work_finished().

+
+
+
+
+

Preconditions

+
+
+
    +
  • +

    This instance holds a valid executor.

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/operator_assign.html b/preview/reference/boost/capy/any_executor/operator_assign.html new file mode 100644 index 0000000..f4e258f --- /dev/null +++ b/preview/reference/boost/capy/any_executor/operator_assign.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::any_executor::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::operator=

+
+
+
+

Copy assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_executor&
+operator=(any_executor const& other) = default;
+
+
+
+
+
+

Description

+
+
+

Shares ownership of the underlying executor with other.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `*this == other`

    +
  • +
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/operator_eq.html b/preview/reference/boost/capy/any_executor/operator_eq.html new file mode 100644 index 0000000..6ebc909 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/operator_eq.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_executor::operator== :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::operator==

+
+
+
+

Compares two executor wrappers for equality.

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator==(any_executor const& other) const noexcept;
+
+
+
+
+
+

Description

+
+
+

Two any_executor instances are equal if they both hold executors of the same type that compare equal, or if both are empty.

+
+
+
+
+

Return Value

+
+
+

true if both wrap equal executors of the same type, or both are empty.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The executor to compare against.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/post.html b/preview/reference/boost/capy/any_executor/post.html new file mode 100644 index 0000000..3e064ed --- /dev/null +++ b/preview/reference/boost/capy/any_executor/post.html @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + boost::capy::any_executor::post :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_executor::post

+
+
+
+

Posts a coroutine handle to the wrapped executor.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+post(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

Posts the coroutine handle to the executor for later execution and returns. The caller should transfer to std::noop_coroutine() after calling this.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to post for resumption.

+
+
+
+

Preconditions

+
+
+
    +
  • +

    This instance holds a valid executor.

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_executor/target_type.html b/preview/reference/boost/capy/any_executor/target_type.html new file mode 100644 index 0000000..7c05e79 --- /dev/null +++ b/preview/reference/boost/capy/any_executor/target_type.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_executor::target_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source.html b/preview/reference/boost/capy/any_read_source.html new file mode 100644 index 0000000..09e36cd --- /dev/null +++ b/preview/reference/boost/capy/any_read_source.html @@ -0,0 +1,511 @@ + + + + + + + + + + + + + + boost::capy::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source

+
+
+
+

Type‐erased wrapper for any ReadSource.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_read_source;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying the ReadSource concept, enabling runtime polymorphism for source read operations. It uses cached awaitable storage to achieve zero steady‐state allocation after construction.

+
+
+

The wrapper supports two construction modes: ‐ Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the source. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to source must outlive this wrapper.

+
+
+
+
+

Awaitable Preallocation

+
+
+

The constructor preallocates storage for the type‐erased awaitable. This reserves all virtual address space at server startup so memory usage can be measured up front, rather than allocating piecemeal as traffic arrives.

+
+
+
+
+

Immediate Completion

+
+
+

Operations complete immediately without suspending when the buffer sequence is empty, or when the underlying source's awaitable reports readiness via await_ready.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations on the same wrapper are undefined behavior.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the source
+any_read_source rs(some_source{args...});
+
+// Reference - wraps without ownership
+some_source source;
+any_read_source rs(&source);
+
+mutable_buffer buf(data, size);
+auto [ec, n] = co_await rs.read(std::span(&buf, 1));
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_read_source [constructor]

Constructors

~any_read_source [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

has_value

Check if the wrapper contains a valid source.

read

Initiate a complete read operation.

read_some

Initiate a partial read operation.

operator bool

Check if the wrapper contains a valid source.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new source after move.

+
+
+
+

See Also

+
+
+

any_read_stream, ReadSource

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2constructor-02.html b/preview/reference/boost/capy/any_read_source/2constructor-02.html new file mode 100644 index 0000000..40871e3 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2constructor-02.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::any_read_source

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_read_source() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_read_source(any_read_source const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_read_source(any_read_source&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a ReadSource.

+
+
+
+
template<ReadSource S>
+requires (!std::same_as<std::decay_t<S>, any_read_source>)
+any_read_source(S s);
+
+
+ +
+

Construct by wrapping a ReadSource without ownership.

+
+
+
+
template<ReadSource S>
+any_read_source(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The source to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2constructor-0a.html b/preview/reference/boost/capy/any_read_source/2constructor-0a.html new file mode 100644 index 0000000..6e9fd42 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2constructor-0a.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::any_read_source

+
+
+
+

Construct by taking ownership of a ReadSource.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ReadSource S>
+requires (!std::same_as<std::decay_t<S>, any_read_source>)
+any_read_source(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the source into this wrapper. The wrapper owns the source and will destroy it.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The source to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2constructor-0b.html b/preview/reference/boost/capy/any_read_source/2constructor-0b.html new file mode 100644 index 0000000..60e8d5f --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2constructor-0b.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::any_read_source

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_source(any_read_source&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers ownership of the wrapped source (if owned) and cached awaitable storage from other. After the move, other is in a default‐constructed state.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2constructor-0d.html b/preview/reference/boost/capy/any_read_source/2constructor-0d.html new file mode 100644 index 0000000..164b6fb --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2constructor-0d.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::any_read_source

+
+
+
+

Non‐copyable.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_source(any_read_source const& other) = delete;
+
+
+
+
+
+

Description

+
+
+

The awaitable cache is per‐instance and cannot be shared.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2constructor-0fc.html b/preview/reference/boost/capy/any_read_source/2constructor-0fc.html new file mode 100644 index 0000000..ebdbd5a --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2constructor-0fc.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::any_read_source

+
+
+
+

Construct by wrapping a ReadSource without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ReadSource S>
+any_read_source(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given source by pointer. The source must remain valid for the lifetime of this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the source to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2constructor-0fd.html b/preview/reference/boost/capy/any_read_source/2constructor-0fd.html new file mode 100644 index 0000000..6a6aebf --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2constructor-0fd.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2conversion.html b/preview/reference/boost/capy/any_read_source/2conversion.html new file mode 100644 index 0000000..75e7bbb --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/2destructor.html b/preview/reference/boost/capy/any_read_source/2destructor.html new file mode 100644 index 0000000..81b58be --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::~any_read_source :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/has_value.html b/preview/reference/boost/capy/any_read_source/has_value.html new file mode 100644 index 0000000..14fefe5 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/has_value.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/operator_assign-08.html b/preview/reference/boost/capy/any_read_source/operator_assign-08.html new file mode 100644 index 0000000..b296d0f --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/operator_assign-08.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_read_source&
+operator=(any_read_source const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+
+
any_read_source&
+operator=(any_read_source&& other) noexcept;
+
+
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/operator_assign-0b.html b/preview/reference/boost/capy/any_read_source/operator_assign-0b.html new file mode 100644 index 0000000..6f6f9c8 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/operator_assign-0b.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_source&
+operator=(any_read_source const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/operator_assign-0e.html b/preview/reference/boost/capy/any_read_source/operator_assign-0e.html new file mode 100644 index 0000000..9313c74 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/operator_assign-0e.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_source&
+operator=(any_read_source&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned source and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/read.html b/preview/reference/boost/capy/any_read_source/read.html new file mode 100644 index 0000000..5b0c466 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/read.html @@ -0,0 +1,469 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::read :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::read

+
+
+
+

Initiate a complete read operation.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<MutableBufferSequence MB>
+io_task<std::size_t>
+read(MB buffers);
+
+
+
+
+
+

Description

+
+
+

Reads data into the provided buffer sequence by forwarding to the underlying source's read operation. Large buffer sequences are processed in windows, with each window forwarded as a separate read call to the underlying source. The operation completes when the entire buffer sequence is filled, end‐of‐file is reached, or an error occurs.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when:

+
+
+
    +
  • +

    The buffer sequence is empty, returning `{error_code{}, 0}`.

    +
  • +
  • +

    The underlying source's `read` awaitable reports immediate readiness via `await_ready`.

    +
  • +
+
+
+
+
+

Postconditions

+
+
+

Exactly one of the following is true on return:

+
+
+
    +
  • +

    **Success**: `!ec` and `n == buffer_size(buffers)`. The entire buffer was filled.

    +
  • +
  • +

    **End‐of‐stream or Error**: `ec` and `n` indicates the number of bytes transferred before the failure.

    +
  • +
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid source (has_value() == true). The caller must not call this function again after a prior call returned an error (including EOF).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to read into.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/read_some.html b/preview/reference/boost/capy/any_read_source/read_some.html new file mode 100644 index 0000000..8cf3c57 --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/read_some.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::read_some :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::read_some

+
+
+
+

Initiate a partial read operation.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<MutableBufferSequence MB>
+auto
+read_some(MB buffers);
+
+
+
+
+
+

Description

+
+
+

Reads one or more bytes into the provided buffer sequence. May fill less than the full sequence.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when:

+
+
+
    +
  • +

    The buffer sequence is empty, returning `{error_code{}, 0}`.

    +
  • +
  • +

    The underlying source's awaitable reports immediate readiness via `await_ready`.

    +
  • +
+
+
+ + + + + +
+ + +
+

This is a partial operation and may not process the entire buffer sequence. Use read for guaranteed complete transfer.

+
+
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid source (has_value() == true). The caller must not call this function again after a prior call returned an error (including EOF).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to read into.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_source/rebind.html b/preview/reference/boost/capy/any_read_source/rebind.html new file mode 100644 index 0000000..c063a1a --- /dev/null +++ b/preview/reference/boost/capy/any_read_source/rebind.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::any_read_source::rebind :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_source::rebind

+
+
+
+

Rebind to a new source after move.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ReadSource S>
+void
+rebind(S& new_source) noexcept;
+
+
+
+
+
+

Description

+
+
+

Updates the internal pointer to reference a new source object. Used by owning wrappers after move assignment when the owned object has moved to a new location.

+
+
+ + + + + +
+ + +
+

Terminates if called with a source of different type than the original.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

new_source

The new source to bind to. Must be the same type as the original source.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream.html b/preview/reference/boost/capy/any_read_stream.html new file mode 100644 index 0000000..b20cd6d --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream.html @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream

+
+
+
+

Type‐erased wrapper for any ReadStream.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_read_stream;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying the ReadStream concept, enabling runtime polymorphism for read operations. It uses cached awaitable storage to achieve zero steady‐state allocation after construction.

+
+
+

The wrapper supports two construction modes: ‐ Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the stream. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to stream must outlive this wrapper.

+
+
+
+
+

Awaitable Preallocation

+
+
+

The constructor preallocates storage for the type‐erased awaitable. This reserves all virtual address space at server startup so memory usage can be measured up front, rather than allocating piecemeal as traffic arrives.

+
+
+
+
+

Immediate Completion

+
+
+

When the underlying stream's awaitable reports ready immediately (e.g. buffered data already available), the wrapper skips coroutine suspension entirely and returns the result inline.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations on the same wrapper are undefined behavior.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the stream
+any_read_stream stream(socket{ioc});
+
+// Reference - wraps without ownership
+socket sock(ioc);
+any_read_stream stream(&sock);
+
+mutable_buffer buf(data, size);
+auto [ec, n] = co_await stream.read_some(buf);
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_read_stream [constructor]

Constructors

~any_read_stream [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

has_value

Check if the wrapper contains a valid stream.

read_some

Initiate an asynchronous read operation.

operator bool

Check if the wrapper contains a valid stream.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new stream after move.

+
+
+
+

Derived Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

any_stream

Type‐erased wrapper for bidirectional streams.

+
+
+
+

See Also

+
+
+

any_write_stream, any_stream, ReadStream

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2constructor-004.html b/preview/reference/boost/capy/any_read_stream/2constructor-004.html new file mode 100644 index 0000000..2390da2 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2constructor-004.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::any_read_stream

+
+
+
+

Non‐copyable.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_stream(any_read_stream const& other) = delete;
+
+
+
+
+
+

Description

+
+
+

The awaitable cache is per‐instance and cannot be shared.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2constructor-007.html b/preview/reference/boost/capy/any_read_stream/2constructor-007.html new file mode 100644 index 0000000..891eeba --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2constructor-007.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::any_read_stream

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_read_stream() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_read_stream(any_read_stream const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_read_stream(any_read_stream&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a ReadStream.

+
+
+
+
template<ReadStream S>
+requires (!std::same_as<std::decay_t<S>, any_read_stream>)
+any_read_stream(S s);
+
+
+ +
+

Construct by wrapping a ReadStream without ownership.

+
+
+
+
template<ReadStream S>
+any_read_stream(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The stream to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2constructor-01.html b/preview/reference/boost/capy/any_read_stream/2constructor-01.html new file mode 100644 index 0000000..09d8137 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2constructor-01.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::any_read_stream

+
+
+
+

Construct by taking ownership of a ReadStream.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ReadStream S>
+requires (!std::same_as<std::decay_t<S>, any_read_stream>)
+any_read_stream(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the stream into this wrapper. The wrapper owns the stream and will destroy it.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The stream to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2constructor-080.html b/preview/reference/boost/capy/any_read_stream/2constructor-080.html new file mode 100644 index 0000000..23edf6a --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2constructor-080.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2constructor-08d.html b/preview/reference/boost/capy/any_read_stream/2constructor-08d.html new file mode 100644 index 0000000..e68b2e6 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2constructor-08d.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::any_read_stream

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_stream(any_read_stream&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers ownership of the wrapped stream (if owned) and cached awaitable storage from other. After the move, other is in a default‐constructed state.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2constructor-0c.html b/preview/reference/boost/capy/any_read_stream/2constructor-0c.html new file mode 100644 index 0000000..b8e329b --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2constructor-0c.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::any_read_stream

+
+
+
+

Construct by wrapping a ReadStream without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ReadStream S>
+any_read_stream(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given stream by pointer. The stream must remain valid for the lifetime of this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the stream to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2conversion.html b/preview/reference/boost/capy/any_read_stream/2conversion.html new file mode 100644 index 0000000..f19f40f --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/2destructor.html b/preview/reference/boost/capy/any_read_stream/2destructor.html new file mode 100644 index 0000000..da3c80f --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::~any_read_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/has_value.html b/preview/reference/boost/capy/any_read_stream/has_value.html new file mode 100644 index 0000000..00354c7 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/has_value.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/operator_assign-04.html b/preview/reference/boost/capy/any_read_stream/operator_assign-04.html new file mode 100644 index 0000000..8ee62b3 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/operator_assign-04.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_stream&
+operator=(any_read_stream const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/operator_assign-09.html b/preview/reference/boost/capy/any_read_stream/operator_assign-09.html new file mode 100644 index 0000000..a157257 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/operator_assign-09.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_read_stream&
+operator=(any_read_stream&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned stream and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/operator_assign-0b.html b/preview/reference/boost/capy/any_read_stream/operator_assign-0b.html new file mode 100644 index 0000000..aee0a37 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/operator_assign-0b.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_read_stream&
+operator=(any_read_stream const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+
+
any_read_stream&
+operator=(any_read_stream&& other) noexcept;
+
+
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/read_some.html b/preview/reference/boost/capy/any_read_stream/read_some.html new file mode 100644 index 0000000..9ed2242 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/read_some.html @@ -0,0 +1,455 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::read_some :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::read_some

+
+
+
+

Initiate an asynchronous read operation.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<MutableBufferSequence MB>
+auto
+read_some(MB buffers);
+
+
+
+
+
+

Description

+
+
+

Reads data into the provided buffer sequence. The operation completes when at least one byte has been read, or an error occurs.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when the underlying stream's awaitable reports immediate readiness via await_ready.

+
+
+ + + + + +
+ + +
+

This is a partial operation and may not process the entire buffer sequence. Use the composed read algorithm for guaranteed complete transfer.

+
+
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid stream (has_value() == true). The caller must not call this function again after a prior call returned an error (including EOF).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence to read into. Passed by value to ensure the sequence lives in the coroutine frame across suspension points.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_read_stream/rebind.html b/preview/reference/boost/capy/any_read_stream/rebind.html new file mode 100644 index 0000000..26c6d25 --- /dev/null +++ b/preview/reference/boost/capy/any_read_stream/rebind.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::any_read_stream::rebind :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_read_stream::rebind

+
+
+
+

Rebind to a new stream after move.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ReadStream S>
+void
+rebind(S& new_stream) noexcept;
+
+
+
+
+
+

Description

+
+
+

Updates the internal pointer to reference a new stream object. Used by owning wrappers after move assignment when the owned object has moved to a new location.

+
+
+ + + + + +
+ + +
+

Terminates if called with a stream of different type than the original.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

new_stream

The new stream to bind to. Must be the same type as the original stream.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream.html b/preview/reference/boost/capy/any_stream.html new file mode 100644 index 0000000..8dc5633 --- /dev/null +++ b/preview/reference/boost/capy/any_stream.html @@ -0,0 +1,546 @@ + + + + + + + + + + + + + + boost::capy::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream

+
+
+
+

Type‐erased wrapper for bidirectional streams.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_stream
+    : public any_read_stream
+    , public any_write_stream
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying both the ReadStream and WriteStream concepts, enabling runtime polymorphism for bidirectional I/O operations.

+
+
+

Inherits from both any_read_stream and any_write_stream, providing read_some and write_some operations. Each base maintains its own cached awaitable storage, allowing concurrent read and write operations.

+
+
+

The wrapper supports two construction modes: ‐ Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the stream. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to stream must outlive this wrapper.

+
+
+
+
+

Implicit Conversion

+
+
+

This class implicitly converts to any_read_stream& or any_write_stream&, allowing it to be passed to functions that accept only one capability. However, do not move through a base reference as this would leave the other base in an invalid state.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations of the same type (two reads or two writes) are undefined behavior. One read and one write may be in flight simultaneously.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the stream
+any_stream stream(socket{ioc});
+
+// Reference - wraps without ownership
+socket sock(ioc);
+any_stream stream(&sock);
+
+// Use read_some from any_read_stream base
+mutable_buffer rbuf(rdata, rsize);
+auto [ec1, n1] = co_await stream.read_some(std::span(&rbuf, 1));
+
+// Use write_some from any_write_stream base
+const_buffer wbuf(wdata, wsize);
+auto [ec2, n2] = co_await stream.write_some(std::span(&wbuf, 1));
+
+// Pass to functions expecting one capability
+void reader(any_read_stream&);
+void writer(any_write_stream&);
+reader(stream);  // Implicit upcast
+writer(stream);  // Implicit upcast
+
+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

any_read_stream

Type‐erased wrapper for any ReadStream.

any_write_stream

Type‐erased wrapper for any WriteStream.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_stream [constructor]

Constructors

~any_stream [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

has_value

Check if the wrapper contains a valid stream.

read_some

Initiate an asynchronous read operation.

write_some

Initiate an asynchronous write operation.

operator bool

Check if the wrapper contains a valid stream.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new stream after move.

+
+
+
+

See Also

+
+
+

any_read_stream, any_write_stream, ReadStream, WriteStream

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2constructor-01.html b/preview/reference/boost/capy/any_stream/2constructor-01.html new file mode 100644 index 0000000..5a111e9 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2constructor-01.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_stream::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2constructor-0b.html b/preview/reference/boost/capy/any_stream/2constructor-0b.html new file mode 100644 index 0000000..b62a071 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2constructor-0b.html @@ -0,0 +1,467 @@ + + + + + + + + + + + + + + boost::capy::any_stream::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::any_stream

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_stream() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_stream(any_stream const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_stream(any_stream&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a bidirectional stream.

+
+
+
+
template<class S>
+requires ReadStream<S> && WriteStream<S> &&
+            (!std::same_as<std::decay_t<S>, any_stream>)
+any_stream(S s);
+
+
+ +
+

Construct by wrapping a bidirectional stream without ownership.

+
+
+
+
template<class S>
+requires ReadStream<S> && WriteStream<S>
+any_stream(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The stream to take ownership of. Must satisfy both ReadStream and WriteStream concepts.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2constructor-0c.html b/preview/reference/boost/capy/any_stream/2constructor-0c.html new file mode 100644 index 0000000..5e8ccb7 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2constructor-0c.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_stream::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::any_stream

+
+
+
+

Construct by wrapping a bidirectional stream without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class S>
+requires ReadStream<S> && WriteStream<S>
+any_stream(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given stream by pointer. The stream must remain valid for the lifetime of this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the stream to wrap. Must satisfy both ReadStream and WriteStream concepts.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2constructor-0d3.html b/preview/reference/boost/capy/any_stream/2constructor-0d3.html new file mode 100644 index 0000000..d01759d --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2constructor-0d3.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_stream::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2constructor-0db.html b/preview/reference/boost/capy/any_stream/2constructor-0db.html new file mode 100644 index 0000000..1141f99 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2constructor-0db.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_stream::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2constructor-0f.html b/preview/reference/boost/capy/any_stream/2constructor-0f.html new file mode 100644 index 0000000..ce6a0b7 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2constructor-0f.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + boost::capy::any_stream::any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::any_stream

+
+
+
+

Construct by taking ownership of a bidirectional stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class S>
+requires ReadStream<S> && WriteStream<S> &&
+            (!std::same_as<std::decay_t<S>, any_stream>)
+any_stream(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the stream into this wrapper. The wrapper owns the stream and will destroy it.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The stream to take ownership of. Must satisfy both ReadStream and WriteStream concepts.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2conversion.html b/preview/reference/boost/capy/any_stream/2conversion.html new file mode 100644 index 0000000..b3b73c7 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2conversion.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::any_stream::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::operator bool

+
+
+
+

Check if the wrapper contains a valid stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
explicit
+operator bool() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Both bases must be valid for the wrapper to be valid.

+
+
+
+
+

Return Value

+
+
+

true if wrapping a stream, false if default‐constructed or moved‐from.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/2destructor.html b/preview/reference/boost/capy/any_stream/2destructor.html new file mode 100644 index 0000000..54f80a9 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_stream::~any_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/has_value.html b/preview/reference/boost/capy/any_stream/has_value.html new file mode 100644 index 0000000..56572c7 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/has_value.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::any_stream::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::has_value

+
+
+
+

Check if the wrapper contains a valid stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+has_value() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Both bases must be valid for the wrapper to be valid.

+
+
+
+
+

Return Value

+
+
+

true if wrapping a stream, false if default‐constructed or moved‐from.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/operator_assign-02.html b/preview/reference/boost/capy/any_stream/operator_assign-02.html new file mode 100644 index 0000000..ae4a455 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/operator_assign-02.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_stream&
+operator=(any_stream&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned stream and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/operator_assign-06.html b/preview/reference/boost/capy/any_stream/operator_assign-06.html new file mode 100644 index 0000000..cda8b52 --- /dev/null +++ b/preview/reference/boost/capy/any_stream/operator_assign-06.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_stream/operator_assign-07.html b/preview/reference/boost/capy/any_stream/operator_assign-07.html new file mode 100644 index 0000000..bd4fabe --- /dev/null +++ b/preview/reference/boost/capy/any_stream/operator_assign-07.html @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + boost::capy::any_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_stream::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_read_stream&
+operator=(any_read_stream const& other) = delete;
+
+
+ +
+

Copy assignment operator

+
+
+
+
any_stream&
+operator=(any_stream const& other) = delete;
+
+
+ +
+

Copy assignment operator

+
+
+
+
any_write_stream&
+operator=(any_write_stream const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+
+
any_read_stream&
+operator=(any_read_stream&& other) noexcept;
+
+
+ +
+

Move assignment operator.

+
+
+
+
any_stream&
+operator=(any_stream&& other) noexcept;
+
+
+ +
+

Move assignment operator.

+
+
+ +
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink.html b/preview/reference/boost/capy/any_write_sink.html new file mode 100644 index 0000000..c95f735 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink

+
+
+
+

Type‐erased wrapper for any WriteSink.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_write_sink;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying the WriteSink concept, enabling runtime polymorphism for sink write operations. It uses cached awaitable storage to achieve zero steady‐state allocation after construction.

+
+
+

The wrapper supports two construction modes: ‐ Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the sink. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to sink must outlive this wrapper.

+
+
+
+
+

Awaitable Preallocation

+
+
+

The constructor preallocates storage for the type‐erased awaitable. This reserves all virtual address space at server startup so memory usage can be measured up front, rather than allocating piecemeal as traffic arrives.

+
+
+
+
+

Immediate Completion

+
+
+

Operations complete immediately without suspending when the buffer sequence is empty, or when the underlying sink's awaitable reports readiness via await_ready.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations on the same wrapper are undefined behavior.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the sink
+any_write_sink ws(some_sink{args...});
+
+// Reference - wraps without ownership
+some_sink sink;
+any_write_sink ws(&sink);
+
+const_buffer buf(data, size);
+auto [ec, n] = co_await ws.write(std::span(&buf, 1));
+auto [ec2] = co_await ws.write_eof();
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_write_sink [constructor]

Constructors

~any_write_sink [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

has_value

Check if the wrapper contains a valid sink.

write

Initiate a complete write operation.

write_eof

write_eof overloads

write_some

Initiate a partial write operation.

operator bool

Check if the wrapper contains a valid sink.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new sink after move.

+
+
+
+

See Also

+
+
+

any_write_stream, WriteSink

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2constructor-01.html b/preview/reference/boost/capy/any_write_sink/2constructor-01.html new file mode 100644 index 0000000..ea5e870 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2constructor-01.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::any_write_sink

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_sink(any_write_sink&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers ownership of the wrapped sink (if owned) and cached awaitable storage from other. After the move, other is in a default‐constructed state.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2constructor-02.html b/preview/reference/boost/capy/any_write_sink/2constructor-02.html new file mode 100644 index 0000000..3c3d44e --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2constructor-02.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::any_write_sink

+
+
+
+

Construct by wrapping a WriteSink without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<WriteSink S>
+any_write_sink(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given sink by pointer. The sink must remain valid for the lifetime of this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the sink to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2constructor-04.html b/preview/reference/boost/capy/any_write_sink/2constructor-04.html new file mode 100644 index 0000000..70f4f76 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2constructor-04.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2constructor-07.html b/preview/reference/boost/capy/any_write_sink/2constructor-07.html new file mode 100644 index 0000000..52d1bc9 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2constructor-07.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::any_write_sink

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_write_sink() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_write_sink(any_write_sink const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_write_sink(any_write_sink&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a WriteSink.

+
+
+
+
template<WriteSink S>
+requires (!std::same_as<std::decay_t<S>, any_write_sink>)
+any_write_sink(S s);
+
+
+ +
+

Construct by wrapping a WriteSink without ownership.

+
+
+
+
template<WriteSink S>
+any_write_sink(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The sink to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2constructor-0f7.html b/preview/reference/boost/capy/any_write_sink/2constructor-0f7.html new file mode 100644 index 0000000..6c78ed9 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2constructor-0f7.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::any_write_sink

+
+
+
+

Construct by taking ownership of a WriteSink.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<WriteSink S>
+requires (!std::same_as<std::decay_t<S>, any_write_sink>)
+any_write_sink(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the sink into this wrapper. The wrapper owns the sink and will destroy it.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The sink to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2constructor-0f9.html b/preview/reference/boost/capy/any_write_sink/2constructor-0f9.html new file mode 100644 index 0000000..038aff7 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2constructor-0f9.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::any_write_sink

+
+
+
+

Non‐copyable.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_sink(any_write_sink const& other) = delete;
+
+
+
+
+
+

Description

+
+
+

The awaitable cache is per‐instance and cannot be shared.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2conversion.html b/preview/reference/boost/capy/any_write_sink/2conversion.html new file mode 100644 index 0000000..76de384 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/2destructor.html b/preview/reference/boost/capy/any_write_sink/2destructor.html new file mode 100644 index 0000000..04bcfef --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::~any_write_sink :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/has_value.html b/preview/reference/boost/capy/any_write_sink/has_value.html new file mode 100644 index 0000000..d553658 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/has_value.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/operator_assign-08b.html b/preview/reference/boost/capy/any_write_sink/operator_assign-08b.html new file mode 100644 index 0000000..c0831e0 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/operator_assign-08b.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_sink&
+operator=(any_write_sink&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned sink and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/operator_assign-08d.html b/preview/reference/boost/capy/any_write_sink/operator_assign-08d.html new file mode 100644 index 0000000..7e04a77 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/operator_assign-08d.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_sink&
+operator=(any_write_sink const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/operator_assign-0c.html b/preview/reference/boost/capy/any_write_sink/operator_assign-0c.html new file mode 100644 index 0000000..0b42cf9 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/operator_assign-0c.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_write_sink&
+operator=(any_write_sink const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+
+
any_write_sink&
+operator=(any_write_sink&& other) noexcept;
+
+
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/rebind.html b/preview/reference/boost/capy/any_write_sink/rebind.html new file mode 100644 index 0000000..9f5102b --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/rebind.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::rebind :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::rebind

+
+
+
+

Rebind to a new sink after move.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<WriteSink S>
+void
+rebind(S& new_sink) noexcept;
+
+
+
+
+
+

Description

+
+
+

Updates the internal pointer to reference a new sink object. Used by owning wrappers after move assignment when the owned object has moved to a new location.

+
+
+ + + + + +
+ + +
+

Terminates if called with a sink of different type than the original.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

new_sink

The new sink to bind to. Must be the same type as the original sink.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/write.html b/preview/reference/boost/capy/any_write_sink/write.html new file mode 100644 index 0000000..e869315 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/write.html @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::write :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::write

+
+
+
+

Initiate a complete write operation.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes data from the provided buffer sequence. The operation completes when all bytes have been consumed, or an error occurs. Forwards to the underlying sink's write operation, windowed through buffer_param when the sequence exceeds the per‐call buffer limit.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when:

+
+
+
    +
  • +

    The buffer sequence is empty, returning `{error_code{}, 0}`.

    +
  • +
  • +

    Every underlying `write` call completes immediately (the wrapped sink reports readiness via `await_ready` on each iteration).

    +
  • +
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence containing data to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/write_eof-05.html b/preview/reference/boost/capy/any_write_sink/write_eof-05.html new file mode 100644 index 0000000..e7f9a60 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/write_eof-05.html @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::write_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::write_eof

+
+
+
+

Atomically write data and signal end‐of‐stream.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write_eof(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes all data from the buffer sequence and then signals end‐of‐stream. The implementation decides how to partition the data across calls to the underlying sink's write and write_eof. When the caller's buffer sequence is non‐empty, the final call to the underlying sink is always write_eof with a non‐empty buffer sequence. When the caller's buffer sequence is empty, only write_eof() with no data is called.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when:

+
+
+
    +
  • +

    The buffer sequence is empty. Only the write_eof() call is performed.

    +
  • +
  • +

    All underlying operations complete immediately (the wrapped sink reports readiness via `await_ready`).

    +
  • +
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence containing data to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/write_eof-0b.html b/preview/reference/boost/capy/any_write_sink/write_eof-0b.html new file mode 100644 index 0000000..a68745f --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/write_eof-0b.html @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::write_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::write_eof

+
+
+
+

write_eof overloads

+
+
+
+
+

Synopses

+
+ +
+

Signal end of data.

+
+
+
+
auto
+write_eof();
+
+
+ +
+

Atomically write data and signal end‐of‐stream.

+
+
+
+
template<ConstBufferSequence CB>
+io_task<std::size_t>
+write_eof(CB buffers);
+
+
+ +
+
+
+

Return Value

+
+
+
    +
  • +

    An awaitable yielding (error_code).

    +
  • +
  • +

    An awaitable yielding (error_code,std::size_t).

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence containing data to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/write_eof-0d.html b/preview/reference/boost/capy/any_write_sink/write_eof-0d.html new file mode 100644 index 0000000..a54ea99 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/write_eof-0d.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::write_eof :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::write_eof

+
+
+
+

Signal end of data.

+
+
+
+
+

Synopsis

+
+ +
+
+
auto
+write_eof();
+
+
+
+
+
+

Description

+
+
+

Indicates that no more data will be written to the sink. The operation completes when the sink is finalized, or an error occurs.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when the underlying sink's awaitable reports immediate readiness via await_ready.

+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code).

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_sink/write_some.html b/preview/reference/boost/capy/any_write_sink/write_some.html new file mode 100644 index 0000000..5979004 --- /dev/null +++ b/preview/reference/boost/capy/any_write_sink/write_some.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_write_sink::write_some :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_sink::write_some

+
+
+
+

Initiate a partial write operation.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+auto
+write_some(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes one or more bytes from the provided buffer sequence. May consume less than the full sequence.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when:

+
+
+
    +
  • +

    The buffer sequence is empty, returning `{error_code{}, 0}`.

    +
  • +
  • +

    The underlying sink's awaitable reports immediate readiness via `await_ready`.

    +
  • +
+
+
+ + + + + +
+ + +
+

This is a partial operation and may not process the entire buffer sequence. Use write for guaranteed complete transfer.

+
+
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid sink (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence containing data to write.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream.html b/preview/reference/boost/capy/any_write_stream.html new file mode 100644 index 0000000..e26cacd --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream.html @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream

+
+
+
+

Type‐erased wrapper for any WriteStream.

+
+
+
+
+

Synopsis

+
+ +
+
+
class any_write_stream;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any type satisfying the WriteStream concept, enabling runtime polymorphism for write operations. It uses cached awaitable storage to achieve zero steady‐state allocation after construction.

+
+
+

The wrapper supports two construction modes: ‐ Owning: Pass by value to transfer ownership. The wrapper allocates storage and owns the stream. ‐ Reference: Pass a pointer to wrap without ownership. The pointed‐to stream must outlive this wrapper.

+
+
+
+
+

Awaitable Preallocation

+
+
+

The constructor preallocates storage for the type‐erased awaitable. This reserves all virtual address space at server startup so memory usage can be measured up front, rather than allocating piecemeal as traffic arrives.

+
+
+
+
+

Immediate Completion

+
+
+

Operations complete immediately without suspending when the buffer sequence is empty, or when the underlying stream's awaitable reports readiness via await_ready.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Concurrent operations on the same wrapper are undefined behavior.

+
+
+
+
+

Example

+
+
+
+
// Owning - takes ownership of the stream
+any_write_stream stream(socket{ioc});
+
+// Reference - wraps without ownership
+socket sock(ioc);
+any_write_stream stream(&sock);
+
+const_buffer buf(data, size);
+auto [ec, n] = co_await stream.write_some(std::span(&buf, 1));
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_write_stream [constructor]

Constructors

~any_write_stream [destructor]

Destructor.

operator= [deleted]

Move assignment operator.

has_value

Check if the wrapper contains a valid stream.

write_some

Initiate an asynchronous write operation.

operator bool

Check if the wrapper contains a valid stream.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

rebind

Rebind to a new stream after move.

+
+
+
+

Derived Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

any_stream

Type‐erased wrapper for bidirectional streams.

+
+
+
+

See Also

+
+
+

any_read_stream, any_stream, WriteStream

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2constructor-01.html b/preview/reference/boost/capy/any_write_stream/2constructor-01.html new file mode 100644 index 0000000..ab43819 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2constructor-01.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::any_write_stream

+
+
+
+

Non‐copyable.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_stream(any_write_stream const& other) = delete;
+
+
+
+
+
+

Description

+
+
+

The awaitable cache is per‐instance and cannot be shared.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2constructor-059.html b/preview/reference/boost/capy/any_write_stream/2constructor-059.html new file mode 100644 index 0000000..df2f68b --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2constructor-059.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::any_write_stream

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_stream(any_write_stream&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers ownership of the wrapped stream (if owned) and cached awaitable storage from other. After the move, other is in a default‐constructed state.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2constructor-05e.html b/preview/reference/boost/capy/any_write_stream/2constructor-05e.html new file mode 100644 index 0000000..1573001 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2constructor-05e.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::any_write_stream

+
+
+
+

Construct by taking ownership of a WriteStream.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<WriteStream S>
+requires (!std::same_as<std::decay_t<S>, any_write_stream>)
+any_write_stream(S s);
+
+
+
+
+
+

Description

+
+
+

Allocates storage and moves the stream into this wrapper. The wrapper owns the stream and will destroy it.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The stream to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2constructor-07.html b/preview/reference/boost/capy/any_write_stream/2constructor-07.html new file mode 100644 index 0000000..ae37ea6 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2constructor-07.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2constructor-09.html b/preview/reference/boost/capy/any_write_stream/2constructor-09.html new file mode 100644 index 0000000..cc7e586 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2constructor-09.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::any_write_stream

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+any_write_stream() = default;
+
+
+ +
+

Non‐copyable.

+
+
+
+
any_write_stream(any_write_stream const& other) = delete;
+
+
+ +
+

Move constructor.

+
+
+
+
any_write_stream(any_write_stream&& other) noexcept;
+
+
+ +
+

Construct by taking ownership of a WriteStream.

+
+
+
+
template<WriteStream S>
+requires (!std::same_as<std::decay_t<S>, any_write_stream>)
+any_write_stream(S s);
+
+
+ +
+

Construct by wrapping a WriteStream without ownership.

+
+
+
+
template<WriteStream S>
+any_write_stream(S* s);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

s

The stream to take ownership of.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2constructor-0f.html b/preview/reference/boost/capy/any_write_stream/2constructor-0f.html new file mode 100644 index 0000000..7e9f08d --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2constructor-0f.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::any_write_stream

+
+
+
+

Construct by wrapping a WriteStream without ownership.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<WriteStream S>
+any_write_stream(S* s);
+
+
+
+
+
+

Description

+
+
+

Wraps the given stream by pointer. The stream must remain valid for the lifetime of this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

Pointer to the stream to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2conversion.html b/preview/reference/boost/capy/any_write_stream/2conversion.html new file mode 100644 index 0000000..d6e0d89 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/2destructor.html b/preview/reference/boost/capy/any_write_stream/2destructor.html new file mode 100644 index 0000000..e975145 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::~any_write_stream :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/has_value.html b/preview/reference/boost/capy/any_write_stream/has_value.html new file mode 100644 index 0000000..40ac2ce --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/has_value.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::has_value :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/operator_assign-05.html b/preview/reference/boost/capy/any_write_stream/operator_assign-05.html new file mode 100644 index 0000000..5fe0ec5 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/operator_assign-05.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
any_write_stream&
+operator=(any_write_stream const& other) = delete;
+
+
+ +
+

Move assignment operator.

+
+
+ +
+ +
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/operator_assign-0b.html b/preview/reference/boost/capy/any_write_stream/operator_assign-0b.html new file mode 100644 index 0000000..1c7fb52 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/operator_assign-0b.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::operator=

+
+
+
+

Move assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_stream&
+operator=(any_write_stream&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Destroys any owned stream and releases existing resources, then transfers ownership from other.

+
+
+
+
+

Return Value

+
+
+

Reference to this wrapper.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The wrapper to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/operator_assign-0c.html b/preview/reference/boost/capy/any_write_stream/operator_assign-0c.html new file mode 100644 index 0000000..1b3428a --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/operator_assign-0c.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
any_write_stream&
+operator=(any_write_stream const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/rebind.html b/preview/reference/boost/capy/any_write_stream/rebind.html new file mode 100644 index 0000000..12c991a --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/rebind.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::rebind :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::rebind

+
+
+
+

Rebind to a new stream after move.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<WriteStream S>
+void
+rebind(S& new_stream) noexcept;
+
+
+
+
+
+

Description

+
+
+

Updates the internal pointer to reference a new stream object. Used by owning wrappers after move assignment when the owned object has moved to a new location.

+
+
+ + + + + +
+ + +
+

Terminates if called with a stream of different type than the original.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

new_stream

The new stream to bind to. Must be the same type as the original stream.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/any_write_stream/write_some.html b/preview/reference/boost/capy/any_write_stream/write_some.html new file mode 100644 index 0000000..eab2b18 --- /dev/null +++ b/preview/reference/boost/capy/any_write_stream/write_some.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + boost::capy::any_write_stream::write_some :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::any_write_stream::write_some

+
+
+
+

Initiate an asynchronous write operation.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence CB>
+auto
+write_some(CB buffers);
+
+
+
+
+
+

Description

+
+
+

Writes data from the provided buffer sequence. The operation completes when at least one byte has been written, or an error occurs.

+
+
+
+
+

Immediate Completion

+
+
+

The operation completes immediately without suspending the calling coroutine when:

+
+
+
    +
  • +

    The buffer sequence is empty, returning `{error_code{}, 0}`.

    +
  • +
  • +

    The underlying stream's awaitable reports immediate readiness via `await_ready`.

    +
  • +
+
+
+ + + + + +
+ + +
+

This is a partial operation and may not process the entire buffer sequence. Use the composed write algorithm for guaranteed complete transfer.

+
+
+
+
+
+
+

Preconditions

+
+
+

The wrapper must contain a valid stream (has_value() == true).

+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code,std::size_t).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

buffers

The buffer sequence containing data to write. Passed by value to ensure the sequence lives in the coroutine frame across suspension points.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event.html b/preview/reference/boost/capy/async_event.html new file mode 100644 index 0000000..67c7217 --- /dev/null +++ b/preview/reference/boost/capy/async_event.html @@ -0,0 +1,503 @@ + + + + + + + + + + + + + + boost::capy::async_event :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event

+
+
+
+

An asynchronous event for coroutines.

+
+
+
+
+

Synopsis

+
+ +
+
+
class async_event;
+
+
+
+
+
+

Description

+
+
+

This event provides a way to notify multiple coroutines that some condition has occurred. When a coroutine awaits an unset event, it suspends and is added to a wait queue. When the event is set, all waiting coroutines are resumed.

+
+
+
+
+

Cancellation

+
+
+

When a coroutine is suspended waiting for the event and its stop token is triggered, the waiter completes with error::canceled instead of waiting for set().

+
+
+

Cancellation only applies while the coroutine is suspended in the wait queue. If the event is already set when wait() is called, the wait completes immediately even if the stop token is already signaled.

+
+
+
+
+

Zero Allocation

+
+
+

No heap allocation occurs for wait operations.

+
+
+
+
+

Thread Safety

+
+
+

The event operations are designed for single‐threaded use on one executor. The stop callback may fire from any thread.

+
+
+
+
+

Example

+
+
+
+
async_event event;
+
+task<> waiter() {
+    auto [ec] = co_await event.wait();
+    if(ec)
+        co_return;
+    // ... event was set ...
+}
+
+task<> notifier() {
+    // ... do some work ...
+    event.set();  // Wake all waiters
+}
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

wait_awaiter

Awaiter returned by wait().

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

async_event [constructor]

Constructors

operator= [deleted]

Copy assignment operator

clear

Clears the event.

is_set

Returns true if the event is currently set.

set

Sets the event.

wait

Returns an awaiter that waits until the event is set.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/2constructor-02.html b/preview/reference/boost/capy/async_event/2constructor-02.html new file mode 100644 index 0000000..708d2ab --- /dev/null +++ b/preview/reference/boost/capy/async_event/2constructor-02.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_event::async_event :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/2constructor-06.html b/preview/reference/boost/capy/async_event/2constructor-06.html new file mode 100644 index 0000000..b208e05 --- /dev/null +++ b/preview/reference/boost/capy/async_event/2constructor-06.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::async_event::async_event :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/2constructor-0b.html b/preview/reference/boost/capy/async_event/2constructor-0b.html new file mode 100644 index 0000000..d7f2d65 --- /dev/null +++ b/preview/reference/boost/capy/async_event/2constructor-0b.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::async_event::async_event :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/clear.html b/preview/reference/boost/capy/async_event/clear.html new file mode 100644 index 0000000..a297cdc --- /dev/null +++ b/preview/reference/boost/capy/async_event/clear.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_event::clear :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/is_set.html b/preview/reference/boost/capy/async_event/is_set.html new file mode 100644 index 0000000..8cb7d27 --- /dev/null +++ b/preview/reference/boost/capy/async_event/is_set.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_event::is_set :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/operator_assign.html b/preview/reference/boost/capy/async_event/operator_assign.html new file mode 100644 index 0000000..b547e0f --- /dev/null +++ b/preview/reference/boost/capy/async_event/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_event::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/set.html b/preview/reference/boost/capy/async_event/set.html new file mode 100644 index 0000000..061fa24 --- /dev/null +++ b/preview/reference/boost/capy/async_event/set.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_event::set :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait.html b/preview/reference/boost/capy/async_event/wait.html new file mode 100644 index 0000000..553234b --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter.html b/preview/reference/boost/capy/async_event/wait_awaiter.html new file mode 100644 index 0000000..67eadc2 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event::wait_awaiter

+
+
+
+

Awaiter returned by wait().

+
+
+
+
+

Synopsis

+
+ +
+
+
class wait_awaiter
+    : public /* implementation-defined */::node
+
+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

/* implementation-defined */::node

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

wait_awaiter [constructor] [deleted]

Constructors

~wait_awaiter [destructor]

Destructor

operator= [deleted]

Assignment operators

await_ready

await_resume

await_suspend

IoAwaitable protocol overload.

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::async_event

An asynchronous event for coroutines.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-002.html b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-002.html new file mode 100644 index 0000000..df5e096 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-002.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::wait_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-00b.html b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-00b.html new file mode 100644 index 0000000..0248706 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-00b.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::wait_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-01.html b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-01.html new file mode 100644 index 0000000..d011a44 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-01.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::wait_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event::wait_awaiter::wait_awaiter

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Copy constructor

+
+
+
+
wait_awaiter(wait_awaiter const& other) = delete;
+
+
+ +
+

Move constructor

+
+
+
+
wait_awaiter(wait_awaiter&& o) noexcept;
+
+
+ +
+

Construct from async_event

+
+
+
+
explicit
+wait_awaiter(async_event* e) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-06.html b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-06.html new file mode 100644 index 0000000..e75bb96 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/2constructor-06.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::wait_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/2destructor.html b/preview/reference/boost/capy/async_event/wait_awaiter/2destructor.html new file mode 100644 index 0000000..9baf96d --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::~wait_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/await_ready.html b/preview/reference/boost/capy/async_event/wait_awaiter/await_ready.html new file mode 100644 index 0000000..8510430 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/await_ready.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::await_ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/await_resume.html b/preview/reference/boost/capy/async_event/wait_awaiter/await_resume.html new file mode 100644 index 0000000..e8378ff --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/await_resume.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/await_suspend.html b/preview/reference/boost/capy/async_event/wait_awaiter/await_suspend.html new file mode 100644 index 0000000..a0e0e94 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/await_suspend.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::await_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event::wait_awaiter::await_suspend

+
+
+
+

IoAwaitable protocol overload.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+await_suspend(
+    std::coroutine_handle h,
+    io_env const* env) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

env

Execution environment for IoAwaitables.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-02.html b/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-02.html new file mode 100644 index 0000000..4f83448 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-02.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event::wait_awaiter::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
wait_awaiter&
+operator=(wait_awaiter const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-06.html b/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-06.html new file mode 100644 index 0000000..60c97c9 --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-06.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event::wait_awaiter::operator=

+
+
+
+

Assignment operators

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
wait_awaiter&
+operator=(wait_awaiter const& other) = delete;
+
+
+ +
+

Move assignment operator

+
+
+
+
wait_awaiter&
+operator=(wait_awaiter&& other) = delete;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-0e.html b/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-0e.html new file mode 100644 index 0000000..7723c3e --- /dev/null +++ b/preview/reference/boost/capy/async_event/wait_awaiter/operator_assign-0e.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_event::wait_awaiter::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_event::wait_awaiter::operator=

+
+
+
+

Move assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
wait_awaiter&
+operator=(wait_awaiter&& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex.html b/preview/reference/boost/capy/async_mutex.html new file mode 100644 index 0000000..9550af3 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + boost::capy::async_mutex :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex

+
+
+
+

An asynchronous mutex for coroutines.

+
+
+
+
+

Synopsis

+
+ +
+
+
class async_mutex;
+
+
+
+
+
+

Description

+
+
+

This mutex provides mutual exclusion for coroutines without blocking. When a coroutine attempts to acquire a locked mutex, it suspends and is added to an intrusive wait queue. When the holder unlocks, the next waiter is resumed with the lock held.

+
+
+
+
+

Cancellation

+
+
+

When a coroutine is suspended waiting for the mutex and its stop token is triggered, the waiter completes with error::canceled instead of acquiring the lock.

+
+
+

Cancellation only applies while the coroutine is suspended in the wait queue. If the mutex is unlocked when lock() is called, the lock is acquired immediately even if the stop token is already signaled.

+
+
+
+
+

Zero Allocation

+
+
+

No heap allocation occurs for lock operations.

+
+
+
+
+

Thread Safety

+
+
+

The mutex operations are designed for single‐threaded use on one executor. The stop callback may fire from any thread.

+
+
+
+
+

Example

+
+
+
+
async_mutex cm;
+
+task<> protected_operation() {
+    auto [ec] = co_await cm.lock();
+    if(ec)
+        co_return;
+    // ... critical section ...
+    cm.unlock();
+}
+
+// Or with RAII:
+task<> protected_operation() {
+    auto [ec, guard] = co_await cm.scoped_lock();
+    if(ec)
+        co_return;
+    // ... critical section ...
+    // unlocks automatically
+}
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

lock_awaiter

Awaiter returned by lock().

lock_guard

RAII lock guard for async_mutex.

lock_guard_awaiter

Awaiter returned by scoped_lock() that returns a lock_guard on resume.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

async_mutex [constructor]

Constructors

operator= [deleted]

Copy assignment operator

is_locked

Returns true if the mutex is currently locked.

lock

Returns an awaiter that acquires the mutex.

scoped_lock

Returns an awaiter that acquires the mutex with RAII.

unlock

Releases the mutex.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/2constructor-01.html b/preview/reference/boost/capy/async_mutex/2constructor-01.html new file mode 100644 index 0000000..808a577 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/2constructor-01.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::async_mutex :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/2constructor-03.html b/preview/reference/boost/capy/async_mutex/2constructor-03.html new file mode 100644 index 0000000..9a0e26a --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/2constructor-03.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::async_mutex :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/2constructor-0a.html b/preview/reference/boost/capy/async_mutex/2constructor-0a.html new file mode 100644 index 0000000..831f23c --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/2constructor-0a.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::async_mutex :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/is_locked.html b/preview/reference/boost/capy/async_mutex/is_locked.html new file mode 100644 index 0000000..51addff --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/is_locked.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::is_locked :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock.html b/preview/reference/boost/capy/async_mutex/lock.html new file mode 100644 index 0000000..55698a7 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter.html b/preview/reference/boost/capy/async_mutex/lock_awaiter.html new file mode 100644 index 0000000..a2c162b --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_awaiter

+
+
+
+

Awaiter returned by lock().

+
+
+
+
+

Synopsis

+
+ +
+
+
class lock_awaiter
+    : public /* implementation-defined */::node
+
+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

/* implementation-defined */::node

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

lock_awaiter [constructor] [deleted]

Constructors

~lock_awaiter [destructor]

Destructor

operator= [deleted]

Assignment operators

await_ready

await_resume

await_suspend

IoAwaitable protocol overload.

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::async_mutex

An asynchronous mutex for coroutines.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-05.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-05.html new file mode 100644 index 0000000..b208ac0 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-05.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::lock_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-061.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-061.html new file mode 100644 index 0000000..59b2d0b --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-061.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::lock_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_awaiter::lock_awaiter

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Copy constructor

+
+
+
+
lock_awaiter(lock_awaiter const& other) = delete;
+
+
+ +
+

Move constructor

+
+
+
+
lock_awaiter(lock_awaiter&& o) noexcept;
+
+
+ +
+

Construct from async_mutex

+
+
+
+
explicit
+lock_awaiter(async_mutex* m) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-063.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-063.html new file mode 100644 index 0000000..118824e --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-063.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::lock_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-0b.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-0b.html new file mode 100644 index 0000000..98bd7a0 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/2constructor-0b.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::lock_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/2destructor.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/2destructor.html new file mode 100644 index 0000000..a64df65 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::~lock_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/await_ready.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/await_ready.html new file mode 100644 index 0000000..b547f9d --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/await_ready.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::await_ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/await_resume.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/await_resume.html new file mode 100644 index 0000000..2d809a5 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/await_resume.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/await_suspend.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/await_suspend.html new file mode 100644 index 0000000..3fcf58a --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/await_suspend.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::await_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_awaiter::await_suspend

+
+
+
+

IoAwaitable protocol overload.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+await_suspend(
+    std::coroutine_handle h,
+    io_env const* env) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

env

Execution environment for IoAwaitables.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-06.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-06.html new file mode 100644 index 0000000..3460c3a --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-06.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_awaiter::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
lock_awaiter&
+operator=(lock_awaiter const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-0b.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-0b.html new file mode 100644 index 0000000..a745329 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-0b.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_awaiter::operator=

+
+
+
+

Assignment operators

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
lock_awaiter&
+operator=(lock_awaiter const& other) = delete;
+
+
+ +
+

Move assignment operator

+
+
+
+
lock_awaiter&
+operator=(lock_awaiter&& other) = delete;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-0f.html b/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-0f.html new file mode 100644 index 0000000..997cc54 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_awaiter/operator_assign-0f.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_awaiter::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_awaiter::operator=

+
+
+
+

Move assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
lock_awaiter&
+operator=(lock_awaiter&& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard.html b/preview/reference/boost/capy/async_mutex/lock_guard.html new file mode 100644 index 0000000..a662a21 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard.html @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_guard

+
+
+
+

RAII lock guard for async_mutex.

+
+
+
+
+

Synopsis

+
+ +
+
+
class lock_guard;
+
+
+
+
+
+

Description

+
+
+

Automatically unlocks the mutex when destroyed.

+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

lock_guard [constructor]

Constructors

~lock_guard [destructor]

Destructor

operator= [deleted]

Assignment operators

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-04.html b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-04.html new file mode 100644 index 0000000..dd97e0c --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-04.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_guard::lock_guard

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor

+
+
+
+
lock_guard() noexcept;
+
+
+ +
+

Copy constructor

+
+
+
+
lock_guard(lock_guard const& other) = delete;
+
+
+ +
+

Move constructor

+
+
+
+
lock_guard(lock_guard&& o) noexcept;
+
+
+ +
+

Construct from async_mutex

+
+
+
+
explicit
+lock_guard(async_mutex* m) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0a.html b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0a.html new file mode 100644 index 0000000..4e6f2d6 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0a.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0e.html b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0e.html new file mode 100644 index 0000000..d357f52 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0e.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0f93.html b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0f93.html new file mode 100644 index 0000000..e703e45 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0f93.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0f9d.html b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0f9d.html new file mode 100644 index 0000000..4807d49 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/2constructor-0f9d.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/2destructor.html b/preview/reference/boost/capy/async_mutex/lock_guard/2destructor.html new file mode 100644 index 0000000..f11904a --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::~lock_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-05.html b/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-05.html new file mode 100644 index 0000000..d99bf27 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-05.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_guard::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
lock_guard&
+operator=(lock_guard const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-0a.html b/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-0a.html new file mode 100644 index 0000000..e84ecd2 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-0a.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-0f.html b/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-0f.html new file mode 100644 index 0000000..748c685 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard/operator_assign-0f.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard_awaiter.html b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter.html new file mode 100644 index 0000000..8c2d17d --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_guard_awaiter

+
+
+
+

Awaiter returned by scoped_lock() that returns a lock_guard on resume.

+
+
+
+
+

Synopsis

+
+ +
+
+
class lock_guard_awaiter;
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

lock_guard_awaiter [constructor]

Construct from async_mutex

await_ready

await_resume

await_suspend

IoAwaitable protocol overload.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/2constructor.html b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/2constructor.html new file mode 100644 index 0000000..e301e13 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/2constructor.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard_awaiter::lock_guard_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_ready.html b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_ready.html new file mode 100644 index 0000000..a6e99c0 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_ready.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard_awaiter::await_ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_resume.html b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_resume.html new file mode 100644 index 0000000..ab733eb --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_resume.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard_awaiter::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_suspend.html b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_suspend.html new file mode 100644 index 0000000..8372be8 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/lock_guard_awaiter/await_suspend.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::lock_guard_awaiter::await_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::async_mutex::lock_guard_awaiter::await_suspend

+
+
+
+

IoAwaitable protocol overload.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+await_suspend(
+    std::coroutine_handle h,
+    io_env const* env) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

env

Execution environment for IoAwaitables.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/operator_assign.html b/preview/reference/boost/capy/async_mutex/operator_assign.html new file mode 100644 index 0000000..f5a2b7a --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/scoped_lock.html b/preview/reference/boost/capy/async_mutex/scoped_lock.html new file mode 100644 index 0000000..ca44fab --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/scoped_lock.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::scoped_lock :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/async_mutex/unlock.html b/preview/reference/boost/capy/async_mutex/unlock.html new file mode 100644 index 0000000..a073b58 --- /dev/null +++ b/preview/reference/boost/capy/async_mutex/unlock.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::async_mutex::unlock :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/awaitable_decomposes_to.html b/preview/reference/boost/capy/awaitable_decomposes_to.html new file mode 100644 index 0000000..8496ea3 --- /dev/null +++ b/preview/reference/boost/capy/awaitable_decomposes_to.html @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + boost::capy::awaitable_decomposes_to :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::awaitable_decomposes_to

+
+
+
+

Concept for awaitables whose return type decomposes to a specific typelist.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    typename A,
+    typename... Types>
+concept awaitable_decomposes_to = requires {
+    typename detail::awaitable_return_t<A>;
+} && decomposes_to<detail::awaitable_return_t<A>, Types...>;
+
+
+
+
+
+

Description

+
+
+

A type satisfies awaitable_decomposes_to if it is an awaitable (has await_resume) and its return type decomposes to the specified typelist.

+
+
+
+
+

Requirements

+
+
+
    +
  • +

    `A` must be an awaitable (directly or via `operator co_await`)

    +
  • +
  • +

    The return type of `await_resume()` must decompose to `Types...`

    +
  • +
+
+
+
+
+

Example

+
+
+
+
// Constrain a function to accept only awaitables that return
+// a decomposable result of (error_code, size_t)
+template<typename A>
+    requires awaitable_decomposes_to<A, std::error_code, std::size_t>
+task<void> process(A&& op)
+{
+    auto [ec, n] = co_await std::forward<A>(op);
+    if (ec)
+        co_return;
+    // process n bytes...
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

A

The awaitable type.

Types

The expected element types after decomposition.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer.html b/preview/reference/boost/capy/basic_string_dynamic_buffer.html new file mode 100644 index 0000000..f0ace90 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer.html @@ -0,0 +1,493 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_string_dynamic_buffer

+
+
+
+

A dynamic buffer using an underlying string

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits = std::char_traits<CharT>,
+    class Allocator = std::allocator<CharT>>
+class basic_string_dynamic_buffer;
+
+
+
+
+
+

Types

+ +
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

basic_string_dynamic_buffer [constructor]

Constructor.

~basic_string_dynamic_buffer [destructor]

Destructor

operator= [deleted]

Assignment.

capacity

commit

consume

data

max_size

prepare

size

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

dynamic_buffer

Create a dynamic buffer from a string.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-00.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-00.html new file mode 100644 index 0000000..af20117 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-00.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::basic_string_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_string_dynamic_buffer::basic_string_dynamic_buffer

+
+
+
+

Constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
basic_string_dynamic_buffer(basic_string_dynamic_buffer&& other) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-06.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-06.html new file mode 100644 index 0000000..617b638 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-06.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::basic_string_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_string_dynamic_buffer::basic_string_dynamic_buffer

+
+
+
+

Constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
explicit
+basic_string_dynamic_buffer(
+    string_type* s,
+    std::size_t max_size = std::size_t(‐1)) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

s

The object to construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-0b.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-0b.html new file mode 100644 index 0000000..295bad6 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/2constructor-0b.html @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::basic_string_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_string_dynamic_buffer::basic_string_dynamic_buffer

+
+
+
+

Constructor.

+
+
+
+
+

Synopses

+
+ +
+

Constructor.

+
+ + +
+

Constructor.

+
+
+
+
explicit
+basic_string_dynamic_buffer(
+    string_type* s,
+    std::size_t max_size = std::size_t(‐1)) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/2destructor.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/2destructor.html new file mode 100644 index 0000000..a7239d3 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::~basic_string_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/capacity.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/capacity.html new file mode 100644 index 0000000..64db8a3 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/capacity.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::capacity :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/commit.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/commit.html new file mode 100644 index 0000000..3340d16 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/commit.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::commit :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/const_buffers_type.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/const_buffers_type.html new file mode 100644 index 0000000..dc141d3 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/const_buffers_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::const_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/consume.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/consume.html new file mode 100644 index 0000000..db4e7ad --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/consume.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/data.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/data.html new file mode 100644 index 0000000..81c81a4 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/data.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/is_dynamic_buffer_adapter.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/is_dynamic_buffer_adapter.html new file mode 100644 index 0000000..d33fe13 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/is_dynamic_buffer_adapter.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::is_dynamic_buffer_adapter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/max_size.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/max_size.html new file mode 100644 index 0000000..ac9afd8 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/max_size.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::max_size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/mutable_buffers_type.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/mutable_buffers_type.html new file mode 100644 index 0000000..311a77a --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/mutable_buffers_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::mutable_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/operator_assign.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/operator_assign.html new file mode 100644 index 0000000..e8b62bb --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_string_dynamic_buffer::operator=

+
+
+
+

Assignment.

+
+
+
+
+

Synopsis

+
+ +
+
+
basic_string_dynamic_buffer&
+operator=(basic_string_dynamic_buffer const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/prepare.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/prepare.html new file mode 100644 index 0000000..4aef365 --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/prepare.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::prepare :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/size.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/size.html new file mode 100644 index 0000000..e1b281f --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/size.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_string_dynamic_buffer/string_type.html b/preview/reference/boost/capy/basic_string_dynamic_buffer/string_type.html new file mode 100644 index 0000000..5908f1d --- /dev/null +++ b/preview/reference/boost/capy/basic_string_dynamic_buffer/string_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::basic_string_dynamic_buffer::string_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0d8.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0d8.html new file mode 100644 index 0000000..c3d77f2 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0d8.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer

+
+
+
+

A dynamic buffer using an underlying vector.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class Allocator = std::allocator<T>>
+requires std::is_fundamental_v<T> && (sizeof(T) == 1)
+class basic_vector_dynamic_buffer;
+
+
+
+
+
+

Description

+
+
+

This class adapts a std::vector of byte‐sized elements to satisfy the DynamicBuffer concept. The vector provides automatic memory management and growth.

+
+
+
+
+

Constraints

+
+
+

The element type T must be a fundamental type with sizeof( T ) == 1. This includes char, unsigned char, signed char, and similar byte‐sized fundamental types.

+
+
+
+
+

Example

+
+
+
+
std::vector<unsigned char> v;
+vector_dynamic_buffer vb( &v );
+
+// Write data
+auto mb = vb.prepare( 100 );
+std::memcpy( mb.data(), "hello", 5 );
+vb.commit( 5 );
+
+// Read data
+auto data = vb.data();
+// process data...
+vb.consume( 5 );
+
+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Unsafe.

+
+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

dynamic_buffer

Create a dynamic buffer from a vector.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

T

The element type. Must be fundamental with sizeof 1.

Allocator

The allocator type for the vector.

+
+
+
+

See Also

+
+
+

flat_dynamic_buffer, circular_dynamic_buffer, string_dynamic_buffer

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df.html new file mode 100644 index 0000000..48ee2ed --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df.html @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer

+
+
+
+

A dynamic buffer using an underlying vector.

+
+
+
+
+

Synopsis

+
+ +
+
+
class basic_vector_dynamic_buffer;
+
+
+
+
+
+

Description

+
+
+

This class adapts a std::vector of byte‐sized elements to satisfy the DynamicBuffer concept. The vector provides automatic memory management and growth.

+
+
+
+
+

Constraints

+
+
+

The element type T must be a fundamental type with sizeof( T ) == 1. This includes char, unsigned char, signed char, and similar byte‐sized fundamental types.

+
+
+
+
+

Example

+
+
+
+
std::vector<unsigned char> v;
+vector_dynamic_buffer vb( &v );
+
+// Write data
+auto mb = vb.prepare( 100 );
+std::memcpy( mb.data(), "hello", 5 );
+vb.commit( 5 );
+
+// Read data
+auto data = vb.data();
+// process data...
+vb.consume( 5 );
+
+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Unsafe.

+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

const_buffers_type

The ConstBufferSequence type for readable bytes.

is_dynamic_buffer_adapter

Indicates this is a DynamicBuffer adapter over external storage.

mutable_buffers_type

The MutableBufferSequence type for writable bytes.

vector_type

The underlying vector type.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

basic_vector_dynamic_buffer [constructor]

Constructors

~basic_vector_dynamic_buffer [destructor]

Destructor

operator= [deleted]

Copy assignment is deleted.

capacity

Return the number of writable bytes without reallocation.

commit

Move bytes from the output to the input sequence.

consume

Remove bytes from the beginning of the input sequence.

data

Return a buffer sequence representing the readable bytes.

max_size

Return the maximum number of bytes the buffer can hold.

prepare

Return a buffer sequence for writing.

size

Return the number of readable bytes.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

T

The element type. Must be fundamental with sizeof 1.

Allocator

The allocator type for the vector.

+
+
+
+

See Also

+
+
+

flat_dynamic_buffer, circular_dynamic_buffer, string_dynamic_buffer

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-05.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-05.html new file mode 100644 index 0000000..6448bf8 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-05.html @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::basic_vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::basic_vector_dynamic_buffer

+
+
+
+

Construct a dynamic buffer over a vector.

+
+
+
+
+

Synopsis

+
+ +
+
+
explicit
+basic_vector_dynamic_buffer(
+    vector_type* v,
+    std::size_t max_size = std::size_t(‐1)) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

v

Pointer to the vector to use as storage.

max_size

Optional maximum size limit. Defaults to the vector's max_size().

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-0c.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-0c.html new file mode 100644 index 0000000..97d76a8 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-0c.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::basic_vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::basic_vector_dynamic_buffer

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Move constructor.

+
+ + +
+

Construct a dynamic buffer over a vector.

+
+
+
+
explicit
+basic_vector_dynamic_buffer(
+    vector_type* v,
+    std::size_t max_size = std::size_t(‐1)) noexcept;
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

v

Pointer to the vector to use as storage.

max_size

Optional maximum size limit. Defaults to the vector's max_size().

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-0e.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-0e.html new file mode 100644 index 0000000..e6a57a7 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2constructor-0e.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::basic_vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::basic_vector_dynamic_buffer

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
basic_vector_dynamic_buffer(basic_vector_dynamic_buffer&& other) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2destructor.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2destructor.html new file mode 100644 index 0000000..9f3ee45 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::~basic_vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/capacity.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/capacity.html new file mode 100644 index 0000000..33fafab --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/capacity.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::capacity :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/commit.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/commit.html new file mode 100644 index 0000000..7fa7b67 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/commit.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::commit :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::commit

+
+
+
+

Move bytes from the output to the input sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+commit(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from prepare. Buffer sequences from data remain valid.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to commit. If greater than the prepared size, all prepared bytes are committed.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/const_buffers_type.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/const_buffers_type.html new file mode 100644 index 0000000..8bd97f0 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/const_buffers_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::const_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/consume.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/consume.html new file mode 100644 index 0000000..7e29822 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/consume.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::consume

+
+
+
+

Remove bytes from the beginning of the input sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+consume(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from data. Buffer sequences from prepare remain valid.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to consume. If greater than size(), all readable bytes are consumed.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/data.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/data.html new file mode 100644 index 0000000..51ad38b --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/data.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/is_dynamic_buffer_adapter.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/is_dynamic_buffer_adapter.html new file mode 100644 index 0000000..5ab64db --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/is_dynamic_buffer_adapter.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::is_dynamic_buffer_adapter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/max_size.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/max_size.html new file mode 100644 index 0000000..4e4ff52 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/max_size.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::max_size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/mutable_buffers_type.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/mutable_buffers_type.html new file mode 100644 index 0000000..f967e8a --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/mutable_buffers_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::mutable_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/operator_assign.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/operator_assign.html new file mode 100644 index 0000000..c85e5dd --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::operator=

+
+
+
+

Copy assignment is deleted.

+
+
+
+
+

Synopsis

+
+ +
+
+
basic_vector_dynamic_buffer&
+operator=(basic_vector_dynamic_buffer const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/prepare.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/prepare.html new file mode 100644 index 0000000..ac3fad4 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/prepare.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::prepare :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::basic_vector_dynamic_buffer::prepare

+
+
+
+

Return a buffer sequence for writing.

+
+
+
+
+

Synopsis

+
+ +
+
+
mutable_buffers_type
+prepare(std::size_t n);
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from prepare.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if size() + n > max_size().

+
+
+
+

Return Value

+
+
+

A mutable buffer sequence of size n.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The desired number of writable bytes.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/size.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/size.html new file mode 100644 index 0000000..aa4e7b9 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/size.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/vector_type.html b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/vector_type.html new file mode 100644 index 0000000..f0087d0 --- /dev/null +++ b/preview/reference/boost/capy/basic_vector_dynamic_buffer-0df/vector_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::basic_vector_dynamic_buffer::vector_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/begin.html b/preview/reference/boost/capy/begin.html new file mode 100644 index 0000000..a0a5d51 --- /dev/null +++ b/preview/reference/boost/capy/begin.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::begin :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/begin_mrdocs_workaround_t.html b/preview/reference/boost/capy/begin_mrdocs_workaround_t.html new file mode 100644 index 0000000..d5aa2b7 --- /dev/null +++ b/preview/reference/boost/capy/begin_mrdocs_workaround_t.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::begin_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::begin_mrdocs_workaround_t

+
+
+
+

Return an iterator to the first buffer in a sequence.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
struct begin_mrdocs_workaround_t;
+
+
+
+
+
+

Description

+
+
+

Handles single buffers and ranges uniformly. For a single buffer, returns a pointer to it (forming a one‐element range).

+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

operator()

Function call operators

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-02.html b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-02.html new file mode 100644 index 0000000..bb299bb --- /dev/null +++ b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-02.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::begin_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-04.html b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-04.html new file mode 100644 index 0000000..5c2bb3e --- /dev/null +++ b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-04.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + boost::capy::begin_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-07.html b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-07.html new file mode 100644 index 0000000..4eb5127 --- /dev/null +++ b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-07.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + boost::capy::begin_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::begin_mrdocs_workaround_t::operator()

+
+
+
+

Function call operators

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<ConstBufferSequence BS>
+requires (!std::convertible_to<BS, const_buffer>)
+auto
+operator()(BS& bs) const noexcept;
+
+
+ +
+
+
template<ConstBufferSequence BS>
+requires (!std::convertible_to<BS, const_buffer>)
+auto
+operator()(BS const& bs) const noexcept;
+
+
+ +
+
+
template<std::convertible_to<const_buffer> ConvertibleToBuffer>
+ConvertibleToBuffer const*
+operator()(ConvertibleToBuffer const& b) const noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-09.html b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-09.html new file mode 100644 index 0000000..985e6cc --- /dev/null +++ b/preview/reference/boost/capy/begin_mrdocs_workaround_t/operator_call-09.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::begin_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array.html b/preview/reference/boost/capy/buffer_array.html new file mode 100644 index 0000000..b0dab91 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array.html @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + boost::capy::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_array

+
+
+
+

A buffer sequence holding up to N buffers.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    std::size_t N,
+    bool IsConst>
+class buffer_array;
+
+
+
+
+
+

Description

+
+
+

This class template stores a fixed‐capacity array of buffer descriptors, where the actual count can vary from 0 to N. It provides efficient storage for small buffer sequences without dynamic allocation.

+
+
+
+
+

Usage

+
+
+
+
void process(ConstBufferSequence auto const& buffers)
+{
+    const_buffer_array<4> bufs(buffers);
+    // use bufs.begin(), bufs.end(), bufs.to_span()
+}
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

value_type

The type of buffer stored in the array.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

buffer_array [constructor]

Constructors

~buffer_array [destructor]

Destructor.

operator=

Copy assignment.

begin

Return an iterator to the beginning.

end

Return an iterator to the end.

to_span

Return a span of the buffers.

operator std::span<value_type>

Conversion to mutable span.

operator std::span<value_type const>

Conversion to const span.

+
+
+
+

Data Members

+
+ +++ + + + + + + + + + + + +

Name

arr_ [variant member]

dummy_ [variant member]

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

boost::capy::tag_invoke

Slice customization point.

boost::capy::tag_invoke

Return the total byte count in O(1).

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

N

Maximum number of buffers the array can hold.

IsConst

If true, holds const_buffer; otherwise mutable_buffer.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-02.html b/preview/reference/boost/capy/buffer_array/2constructor-02.html new file mode 100644 index 0000000..512f60e --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-02.html @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_array::buffer_array

+
+
+
+

Construct from a buffer sequence with overflow checking.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class BS>
+requires (IsConst ? ConstBufferSequence<BS> : MutableBufferSequence<BS>)
+buffer_array(
+    std::in_place_t,
+    BS const& bs);
+
+
+
+
+
+

Description

+
+
+

Copies buffer descriptors from the source sequence into the internal array.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::length_error

if the sequence contains more than N non‐empty buffers.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

bs

The buffer sequence to copy from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-03.html b/preview/reference/boost/capy/buffer_array/2constructor-03.html new file mode 100644 index 0000000..16f6215 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-03.html @@ -0,0 +1,422 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_array::buffer_array

+
+
+
+

Construct from an iterator range.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class Iterator>
+buffer_array(
+    Iterator first,
+    Iterator last) noexcept;
+
+
+
+
+
+

Description

+
+
+

Copies up to N non‐empty buffer descriptors from the range [first, last). If the range contains more than N non‐empty buffers, excess buffers are silently ignored.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

first

Iterator to the first buffer descriptor.

last

Iterator past the last buffer descriptor.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-05.html b/preview/reference/boost/capy/buffer_array/2constructor-05.html new file mode 100644 index 0000000..7304d23 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-05.html @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_array::buffer_array

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
buffer_array() noexcept;
+
+
+ +
+

Copy constructor.

+
+
+
+
buffer_array(buffer_array const& other) noexcept;
+
+
+ +
+

Construct from a single buffer.

+
+
+
+
buffer_array(value_type const& b) noexcept;
+
+
+ +
+

Construct from a buffer sequence.

+
+
+
+
template<class BS>
+requires (IsConst ? ConstBufferSequence<BS> : MutableBufferSequence<BS>)
+            && (!std::same_as<std::remove_cvref_t<BS>, buffer_array>)
+            && (!std::same_as<std::remove_cvref_t<BS>, value_type>)
+buffer_array(BS const& bs) noexcept;
+
+
+ +
+

Construct from an iterator range.

+
+
+
+
template<class Iterator>
+buffer_array(
+    Iterator first,
+    Iterator last) noexcept;
+
+
+ +
+

Construct from a buffer sequence with overflow checking.

+
+
+
+
template<class BS>
+requires (IsConst ? ConstBufferSequence<BS> : MutableBufferSequence<BS>)
+buffer_array(
+    std::in_place_t,
+    BS const& bs);
+
+
+ +
+

Construct from an iterator range with overflow checking.

+
+
+
+
template<class Iterator>
+buffer_array(
+    std::in_place_t,
+    Iterator first,
+    Iterator last);
+
+
+ +
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::length_error

if the sequence contains more than N non‐empty buffers.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

b

The buffer to store.

bs

The buffer sequence to copy from.

first

Iterator to the first buffer descriptor.

last

Iterator past the last buffer descriptor.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-06.html b/preview/reference/boost/capy/buffer_array/2constructor-06.html new file mode 100644 index 0000000..323b84f --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-06.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-08.html b/preview/reference/boost/capy/buffer_array/2constructor-08.html new file mode 100644 index 0000000..9a17e93 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-08.html @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_array::buffer_array

+
+
+
+

Construct from a buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class BS>
+requires (IsConst ? ConstBufferSequence<BS> : MutableBufferSequence<BS>)
+            && (!std::same_as<std::remove_cvref_t<BS>, buffer_array>)
+            && (!std::same_as<std::remove_cvref_t<BS>, value_type>)
+buffer_array(BS const& bs) noexcept;
+
+
+
+
+
+

Description

+
+
+

Copies up to N buffer descriptors from the source sequence into the internal array. If the sequence contains more than N non‐empty buffers, excess buffers are silently ignored.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

bs

The buffer sequence to copy from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-0a.html b/preview/reference/boost/capy/buffer_array/2constructor-0a.html new file mode 100644 index 0000000..9b20e02 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-0a.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-0f5.html b/preview/reference/boost/capy/buffer_array/2constructor-0f5.html new file mode 100644 index 0000000..727e141 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-0f5.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2constructor-0f9.html b/preview/reference/boost/capy/buffer_array/2constructor-0f9.html new file mode 100644 index 0000000..4fa2ae0 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2constructor-0f9.html @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_array::buffer_array

+
+
+
+

Construct from an iterator range with overflow checking.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class Iterator>
+buffer_array(
+    std::in_place_t,
+    Iterator first,
+    Iterator last);
+
+
+
+
+
+

Description

+
+
+

Copies all non‐empty buffer descriptors from the range [first, last) into the internal array.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::length_error

if the range contains more than N non‐empty buffers.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

first

Iterator to the first buffer descriptor.

last

Iterator past the last buffer descriptor.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2conversion-00.html b/preview/reference/boost/capy/buffer_array/2conversion-00.html new file mode 100644 index 0000000..8b69152 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2conversion-00.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::operator std::span<value_type const> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2conversion-08.html b/preview/reference/boost/capy/buffer_array/2conversion-08.html new file mode 100644 index 0000000..604c665 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2conversion-08.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::operator std::span<value_type> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/2destructor.html b/preview/reference/boost/capy/buffer_array/2destructor.html new file mode 100644 index 0000000..fbe7a8a --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::~buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/arr_.html b/preview/reference/boost/capy/buffer_array/arr_.html new file mode 100644 index 0000000..df6db8a --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/arr_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::arr_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/begin-02.html b/preview/reference/boost/capy/buffer_array/begin-02.html new file mode 100644 index 0000000..58c71f4 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/begin-02.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::begin :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/begin-0a4.html b/preview/reference/boost/capy/buffer_array/begin-0a4.html new file mode 100644 index 0000000..46e90e6 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/begin-0a4.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::begin :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/begin-0a7.html b/preview/reference/boost/capy/buffer_array/begin-0a7.html new file mode 100644 index 0000000..1415d70 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/begin-0a7.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::begin :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/dummy_.html b/preview/reference/boost/capy/buffer_array/dummy_.html new file mode 100644 index 0000000..f2dd53b --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/dummy_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::dummy_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/end-08.html b/preview/reference/boost/capy/buffer_array/end-08.html new file mode 100644 index 0000000..1655bbe --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/end-08.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::end :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/end-0b2.html b/preview/reference/boost/capy/buffer_array/end-0b2.html new file mode 100644 index 0000000..53c198d --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/end-0b2.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::end :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/end-0bc.html b/preview/reference/boost/capy/buffer_array/end-0bc.html new file mode 100644 index 0000000..4c080c4 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/end-0bc.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::end :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/operator_assign.html b/preview/reference/boost/capy/buffer_array/operator_assign.html new file mode 100644 index 0000000..cf21e27 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/to_span-01.html b/preview/reference/boost/capy/buffer_array/to_span-01.html new file mode 100644 index 0000000..f24efab --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/to_span-01.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::to_span :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/to_span-06.html b/preview/reference/boost/capy/buffer_array/to_span-06.html new file mode 100644 index 0000000..fd88de9 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/to_span-06.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::to_span :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/to_span-0a.html b/preview/reference/boost/capy/buffer_array/to_span-0a.html new file mode 100644 index 0000000..b08dae1 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/to_span-0a.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::to_span :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_array/value_type.html b/preview/reference/boost/capy/buffer_array/value_type.html new file mode 100644 index 0000000..7ce0484 --- /dev/null +++ b/preview/reference/boost/capy/buffer_array/value_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::buffer_array::value_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_copy.html b/preview/reference/boost/capy/buffer_copy.html new file mode 100644 index 0000000..f018035 --- /dev/null +++ b/preview/reference/boost/capy/buffer_copy.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_copy :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_copy_mrdocs_workaround_t.html b/preview/reference/boost/capy/buffer_copy_mrdocs_workaround_t.html new file mode 100644 index 0000000..cbeef0e --- /dev/null +++ b/preview/reference/boost/capy/buffer_copy_mrdocs_workaround_t.html @@ -0,0 +1,460 @@ + + + + + + + + + + + + + + boost::capy::buffer_copy_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_copy_mrdocs_workaround_t

+
+
+
+

Copy the contents of a buffer sequence into another buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
struct buffer_copy_mrdocs_workaround_t;
+
+
+
+
+
+

Description

+
+
+

This function copies bytes from the constant buffer sequence src into the mutable buffer sequence dest, stopping when any limit is reached.

+
+
+
+
+

Constraints

+
+
+
+
MutableBufferSequence<decltype(dest)> &&
+ConstBufferSequence<decltype(src)>
+
+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+
+
+

Return Value

+
+
+

The number of bytes copied, equal to std::min(size(dest), size(src), at_most).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

dest

The destination buffer sequence.

src

The source buffer sequence.

at_most

The maximum bytes to copy. Default copies all available.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_copy_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/buffer_copy_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..3335dd8 --- /dev/null +++ b/preview/reference/boost/capy/buffer_copy_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::buffer_copy_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_empty.html b/preview/reference/boost/capy/buffer_empty.html new file mode 100644 index 0000000..a9b934a --- /dev/null +++ b/preview/reference/boost/capy/buffer_empty.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_empty :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_empty_mrdocs_workaround_t.html b/preview/reference/boost/capy/buffer_empty_mrdocs_workaround_t.html new file mode 100644 index 0000000..c1163c2 --- /dev/null +++ b/preview/reference/boost/capy/buffer_empty_mrdocs_workaround_t.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::buffer_empty_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_empty_mrdocs_workaround_t

+
+
+
+

Check if a buffer sequence contains no data.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
struct buffer_empty_mrdocs_workaround_t;
+
+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+
+
+

Return Value

+
+
+

true if all buffers have size zero or the sequence is empty.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_empty_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/buffer_empty_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..8b20bb5 --- /dev/null +++ b/preview/reference/boost/capy/buffer_empty_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::buffer_empty_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_length.html b/preview/reference/boost/capy/buffer_length.html new file mode 100644 index 0000000..ff15594 --- /dev/null +++ b/preview/reference/boost/capy/buffer_length.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::buffer_length :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_length

+
+
+
+

Return the number of buffer elements in a sequence.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<ConstBufferSequence CB>
+std::size_t
+buffer_length(CB const& bs);
+
+
+
+
+
+

Description

+
+
+

Counts the number of individual buffer objects, not bytes. For a single buffer, returns 1. For a range, returns the distance from begin to end.

+
+
+
+
+

Return Value

+
+
+

the number of buffer elements in a sequence.

+
+
+
+
+

See Also

+
+
+

buffer_size

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a.html b/preview/reference/boost/capy/buffer_param-0a.html new file mode 100644 index 0000000..c0d490e --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a.html @@ -0,0 +1,581 @@ + + + + + + + + + + + + + + boost::capy::buffer_param :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_param

+
+
+
+

A buffer sequence wrapper providing windowed access.

+
+
+
+
+

Synopsis

+
+ +
+
+
class buffer_param;
+
+
+
+
+
+

Description

+
+
+

This template class wraps any buffer sequence and provides incremental access through a sliding window of buffer descriptors. It handles both const and mutable buffer sequences automatically.

+
+
+
+
+

Coroutine Lifetime Requirement

+
+
+

When used in coroutine APIs, the outer template function MUST accept the buffer sequence parameter BY VALUE:

+
+
+
+
task<> write(ConstBufferSequence auto buffers);   // CORRECT
+task<> write(ConstBufferSequence auto& buffers);  // WRONG - dangling reference
+
+
+
+

Pass‐by‐value ensures the buffer sequence is copied into the coroutine frame and remains valid across suspension points. References would dangle when the caller's scope exits before the coroutine resumes.

+
+
+
+
+

Purpose

+
+
+

When iterating through large buffer sequences, it is often more efficient to process buffers in batches rather than one at a time. This class maintains a window of up to max_size buffer descriptors, automatically refilling from the underlying sequence as buffers are consumed.

+
+
+
+
+

Usage

+
+
+

Create a buffer_param from any buffer sequence and use data() to get the current window of buffers. After processing some bytes, call consume() to advance through the sequence.

+
+
+
+
task<> send(ConstBufferSequence auto buffers)
+{
+    buffer_param bp(buffers);
+    while(true)
+    {
+        auto bufs = bp.data();
+        if(bufs.empty())
+            break;
+        auto n = co_await do_something(bufs);
+        bp.consume(n);
+    }
+}
+
+
+
+
+
+

Virtual Interface Pattern

+
+
+

This class enables passing arbitrary buffer sequences through a virtual function boundary. The template function captures the buffer sequence by value and drives the iteration, while the virtual function receives a simple span:

+
+
+
+
class base
+{
+public:
+    task<> write(ConstBufferSequence auto buffers)
+    {
+        buffer_param bp(buffers);
+        while(true)
+        {
+            auto bufs = bp.data();
+            if(bufs.empty())
+                break;
+            std::size_t n = 0;
+            co_await write_impl(bufs, n);
+            bp.consume(n);
+        }
+    }
+
+protected:
+    virtual task<> write_impl(
+        std::span<const_buffer> buffers,
+        std::size_t& bytes_written) = 0;
+};
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

buffer_type

The buffer type (const_buffer or mutable_buffer)

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

buffer_param [constructor]

Construct from a buffer sequence.

consume

Consume bytes from the buffer sequence.

data

Return the current window of buffer descriptors.

more

Check if more buffers exist beyond the current window.

+
+
+
+

Data Members

+
+ +++ + + + + + + + + + + + +

Name

arr_ [variant member]

dummy_ [variant member]

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

BS

The buffer sequence type. Must satisfy either ConstBufferSequence or MutableBufferSequence.

+
+
+
+

See Also

+
+
+

ConstBufferSequence, MutableBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/2constructor.html b/preview/reference/boost/capy/buffer_param-0a/2constructor.html new file mode 100644 index 0000000..e834e2c --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/2constructor.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::buffer_param :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_param::buffer_param

+
+
+
+

Construct from a buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
explicit
+buffer_param(BS const& bs);
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

bs

The buffer sequence to wrap. The caller must ensure the buffer sequence remains valid for the lifetime of this object.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/arr_.html b/preview/reference/boost/capy/buffer_param-0a/arr_.html new file mode 100644 index 0000000..d310a0f --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/arr_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::arr_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/buffer_type.html b/preview/reference/boost/capy/buffer_param-0a/buffer_type.html new file mode 100644 index 0000000..1bc2afc --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/buffer_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::buffer_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/consume.html b/preview/reference/boost/capy/buffer_param-0a/consume.html new file mode 100644 index 0000000..9002fe2 --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/consume.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_param::consume

+
+
+
+

Consume bytes from the buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+consume(std::size_t n);
+
+
+
+
+
+

Description

+
+
+

Advances the current position by n bytes, consuming data from the front of the sequence. Partially consumed buffers are adjusted in place.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

Number of bytes to consume.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/data.html b/preview/reference/boost/capy/buffer_param-0a/data.html new file mode 100644 index 0000000..576630b --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/data.html @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_param::data

+
+
+
+

Return the current window of buffer descriptors.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::span<buffer_type>
+data();
+
+
+
+
+
+

Description

+
+
+

Returns a span of buffer descriptors representing the currently available portion of the buffer sequence. The span contains at most max_size buffers.

+
+
+

When the current window is exhausted, this function automatically refills from the underlying sequence.

+
+
+
+
+

Return Value

+
+
+

A span of buffer descriptors. Empty span indicates no more data is available.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/dummy_.html b/preview/reference/boost/capy/buffer_param-0a/dummy_.html new file mode 100644 index 0000000..4b216d8 --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/dummy_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::dummy_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0a/more.html b/preview/reference/boost/capy/buffer_param-0a/more.html new file mode 100644 index 0000000..491b01b --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0a/more.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::buffer_param::more :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_param::more

+
+
+
+

Check if more buffers exist beyond the current window.

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+more() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Returns true if the underlying buffer sequence has additional buffers that have not yet been loaded into the current window. Call after data to determine whether the current window is the last one.

+
+
+
+
+

Return Value

+
+
+

true if more buffers remain in the sequence.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0b.html b/preview/reference/boost/capy/buffer_param-0b.html new file mode 100644 index 0000000..fe34541 --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0b.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::buffer_param<BS> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_param-0d.html b/preview/reference/boost/capy/buffer_param-0d.html new file mode 100644 index 0000000..18c674b --- /dev/null +++ b/preview/reference/boost/capy/buffer_param-0d.html @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + boost::capy::buffer_param :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_param

+
+
+
+

A buffer sequence wrapper providing windowed access.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class BS,
+    bool MakeConst = false>
+requires ConstBufferSequence<BS> || MutableBufferSequence<BS>
+class buffer_param;
+
+
+
+
+
+

Description

+
+
+

This template class wraps any buffer sequence and provides incremental access through a sliding window of buffer descriptors. It handles both const and mutable buffer sequences automatically.

+
+
+
+
+

Coroutine Lifetime Requirement

+
+
+

When used in coroutine APIs, the outer template function MUST accept the buffer sequence parameter BY VALUE:

+
+
+
+
task<> write(ConstBufferSequence auto buffers);   // CORRECT
+task<> write(ConstBufferSequence auto& buffers);  // WRONG - dangling reference
+
+
+
+

Pass‐by‐value ensures the buffer sequence is copied into the coroutine frame and remains valid across suspension points. References would dangle when the caller's scope exits before the coroutine resumes.

+
+
+
+
+

Purpose

+
+
+

When iterating through large buffer sequences, it is often more efficient to process buffers in batches rather than one at a time. This class maintains a window of up to max_size buffer descriptors, automatically refilling from the underlying sequence as buffers are consumed.

+
+
+
+
+

Usage

+
+
+

Create a buffer_param from any buffer sequence and use data() to get the current window of buffers. After processing some bytes, call consume() to advance through the sequence.

+
+
+
+
task<> send(ConstBufferSequence auto buffers)
+{
+    buffer_param bp(buffers);
+    while(true)
+    {
+        auto bufs = bp.data();
+        if(bufs.empty())
+            break;
+        auto n = co_await do_something(bufs);
+        bp.consume(n);
+    }
+}
+
+
+
+
+
+

Virtual Interface Pattern

+
+
+

This class enables passing arbitrary buffer sequences through a virtual function boundary. The template function captures the buffer sequence by value and drives the iteration, while the virtual function receives a simple span:

+
+
+
+
class base
+{
+public:
+    task<> write(ConstBufferSequence auto buffers)
+    {
+        buffer_param bp(buffers);
+        while(true)
+        {
+            auto bufs = bp.data();
+            if(bufs.empty())
+                break;
+            std::size_t n = 0;
+            co_await write_impl(bufs, n);
+            bp.consume(n);
+        }
+    }
+
+protected:
+    virtual task<> write_impl(
+        std::span<const_buffer> buffers,
+        std::size_t& bytes_written) = 0;
+};
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

BS

The buffer sequence type. Must satisfy either ConstBufferSequence or MutableBufferSequence.

+
+
+
+

See Also

+
+
+

ConstBufferSequence, MutableBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_size.html b/preview/reference/boost/capy/buffer_size.html new file mode 100644 index 0000000..1ee5bfb --- /dev/null +++ b/preview/reference/boost/capy/buffer_size.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::buffer_size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_size_mrdocs_workaround_t.html b/preview/reference/boost/capy/buffer_size_mrdocs_workaround_t.html new file mode 100644 index 0000000..3b7c5b5 --- /dev/null +++ b/preview/reference/boost/capy/buffer_size_mrdocs_workaround_t.html @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + boost::capy::buffer_size_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_size_mrdocs_workaround_t

+
+
+
+

Return the total byte count across all buffers in a sequence.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
struct buffer_size_mrdocs_workaround_t;
+
+
+
+
+
+

Description

+
+
+

Sums the size() of each buffer in the sequence. This differs from buffer_length which counts the number of buffer elements.

+
+
+
+
+

Example

+
+
+
+
std::array<mutable_buffer, 2> bufs = { ... };
+std::size_t total = buffer_size( bufs );  // sum of both sizes
+
+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_size_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/buffer_size_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..834af8c --- /dev/null +++ b/preview/reference/boost/capy/buffer_size_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::buffer_size_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/buffer_type.html b/preview/reference/boost/capy/buffer_type.html new file mode 100644 index 0000000..d9a6a5b --- /dev/null +++ b/preview/reference/boost/capy/buffer_type.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::buffer_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::buffer_type

+
+
+
+

Alias for mutable_buffer or const_buffer based on sequence type.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<typename BS>
+using buffer_type = std::conditional_t<MutableBufferSequence<BS>, mutable_buffer, const_buffer>;
+
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer.html b/preview/reference/boost/capy/circular_dynamic_buffer.html new file mode 100644 index 0000000..93c7839 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer.html @@ -0,0 +1,514 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer

+
+
+
+

A fixed‐capacity circular buffer satisfying DynamicBuffer.

+
+
+
+
+

Synopsis

+
+ +
+
+
class circular_dynamic_buffer;
+
+
+
+
+
+

Description

+
+
+

This class implements a circular ( ring ) buffer with fixed capacity determined at construction. Unlike linear buffers, data can wrap around from the end to the beginning, enabling efficient FIFO operations without memory copies.

+
+
+

Buffer sequences returned from data and prepare may contain up to two elements to represent wrapped regions.

+
+
+
+
+

Example

+
+
+
+
char storage[1024];
+circular_dynamic_buffer cb( storage, sizeof( storage ) );
+
+// Write data
+auto mb = cb.prepare( 100 );
+std::memcpy( mb.data(), "hello", 5 );
+cb.commit( 5 );
+
+// Read data
+auto cb_data = cb.data();
+// process cb_data...
+cb.consume( 5 );
+
+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Unsafe.

+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

const_buffers_type

The ConstBufferSequence type for readable bytes.

is_dynamic_buffer_adapter

Indicates this is a DynamicBuffer adapter over external storage.

mutable_buffers_type

The MutableBufferSequence type for writable bytes.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

circular_dynamic_buffer [constructor]

Constructors

operator=

Copy assignment.

capacity

Return the number of writable bytes without reallocation.

commit

Move bytes from the output to the input sequence.

consume

Remove bytes from the beginning of the input sequence.

data

Return a buffer sequence representing the readable bytes.

max_size

Return the maximum number of bytes the buffer can hold.

prepare

Return a buffer sequence for writing.

size

Return the number of readable bytes.

+
+
+
+

See Also

+
+
+

flat_dynamic_buffer, string_dynamic_buffer

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-01.html b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-01.html new file mode 100644 index 0000000..f64af76 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-01.html @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::circular_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::circular_dynamic_buffer

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Construct an empty circular buffer with zero capacity.

+
+
+
+
constexpr
+circular_dynamic_buffer() = default;
+
+
+ +
+

Copy constructor.

+
+
+
+
constexpr
+circular_dynamic_buffer(circular_dynamic_buffer const& other) = default;
+
+
+ +
+

Construct a circular buffer over existing storage.

+
+
+
+
circular_dynamic_buffer(
+    void* base,
+    std::size_t capacity) noexcept;
+
+
+ +
+

Construct a circular buffer with initial readable bytes.

+
+
+
+
circular_dynamic_buffer(
+    void* base,
+    std::size_t capacity,
+    std::size_t initial_size);
+
+
+ +
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if initial_size > capacity.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

base

Pointer to the storage.

capacity

Size of the storage in bytes.

initial_size

Number of bytes already present as readable. Must not exceed capacity.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0b.html b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0b.html new file mode 100644 index 0000000..9f59b71 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0b.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::circular_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::circular_dynamic_buffer

+
+
+
+

Copy constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+circular_dynamic_buffer(circular_dynamic_buffer const& other) = default;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0c.html b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0c.html new file mode 100644 index 0000000..116f130 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0c.html @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::circular_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::circular_dynamic_buffer

+
+
+
+

Construct a circular buffer with initial readable bytes.

+
+
+
+
+

Synopsis

+
+ +
+
+
circular_dynamic_buffer(
+    void* base,
+    std::size_t capacity,
+    std::size_t initial_size);
+
+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if initial_size > capacity.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

base

Pointer to the storage.

capacity

Size of the storage in bytes.

initial_size

Number of bytes already present as readable. Must not exceed capacity.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0e.html b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0e.html new file mode 100644 index 0000000..3c163a5 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0e.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::circular_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0f.html b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0f.html new file mode 100644 index 0000000..1f09b96 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/2constructor-0f.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::circular_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::circular_dynamic_buffer

+
+
+
+

Construct a circular buffer over existing storage.

+
+
+
+
+

Synopsis

+
+ +
+
+
circular_dynamic_buffer(
+    void* base,
+    std::size_t capacity) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

base

Pointer to the storage.

capacity

Size of the storage in bytes.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/capacity.html b/preview/reference/boost/capy/circular_dynamic_buffer/capacity.html new file mode 100644 index 0000000..e106fb5 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/capacity.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::capacity :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/commit.html b/preview/reference/boost/capy/circular_dynamic_buffer/commit.html new file mode 100644 index 0000000..9877f2b --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/commit.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::commit :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::commit

+
+
+
+

Move bytes from the output to the input sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+commit(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from prepare. Buffer sequences from data remain valid.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to commit. If greater than the prepared size, all prepared bytes are committed.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/const_buffers_type.html b/preview/reference/boost/capy/circular_dynamic_buffer/const_buffers_type.html new file mode 100644 index 0000000..f968e9d --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/const_buffers_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::const_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/consume.html b/preview/reference/boost/capy/circular_dynamic_buffer/consume.html new file mode 100644 index 0000000..1d464a5 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/consume.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::consume

+
+
+
+

Remove bytes from the beginning of the input sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+consume(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from data. Buffer sequences from prepare remain valid.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to consume. If greater than size(), all readable bytes are consumed.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/data.html b/preview/reference/boost/capy/circular_dynamic_buffer/data.html new file mode 100644 index 0000000..f0fa906 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/data.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/is_dynamic_buffer_adapter.html b/preview/reference/boost/capy/circular_dynamic_buffer/is_dynamic_buffer_adapter.html new file mode 100644 index 0000000..f5e0f91 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/is_dynamic_buffer_adapter.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::is_dynamic_buffer_adapter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/max_size.html b/preview/reference/boost/capy/circular_dynamic_buffer/max_size.html new file mode 100644 index 0000000..4aa1473 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/max_size.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::max_size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/mutable_buffers_type.html b/preview/reference/boost/capy/circular_dynamic_buffer/mutable_buffers_type.html new file mode 100644 index 0000000..616b320 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/mutable_buffers_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::mutable_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/operator_assign.html b/preview/reference/boost/capy/circular_dynamic_buffer/operator_assign.html new file mode 100644 index 0000000..cd54cd0 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/operator_assign.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::operator=

+
+
+
+

Copy assignment.

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+circular_dynamic_buffer&
+operator=(circular_dynamic_buffer const& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/prepare.html b/preview/reference/boost/capy/circular_dynamic_buffer/prepare.html new file mode 100644 index 0000000..c015f13 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/prepare.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::prepare :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::circular_dynamic_buffer::prepare

+
+
+
+

Return a buffer sequence for writing.

+
+
+
+
+

Synopsis

+
+ +
+
+
mutable_buffers_type
+prepare(std::size_t n);
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from prepare.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::length_error

if size() + n > max_size().

+
+
+
+

Return Value

+
+
+

A mutable buffer sequence of size n.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The desired number of writable bytes.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/circular_dynamic_buffer/size.html b/preview/reference/boost/capy/circular_dynamic_buffer/size.html new file mode 100644 index 0000000..57a0993 --- /dev/null +++ b/preview/reference/boost/capy/circular_dynamic_buffer/size.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::circular_dynamic_buffer::size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/cond.html b/preview/reference/boost/capy/cond.html new file mode 100644 index 0000000..9963b40 --- /dev/null +++ b/preview/reference/boost/capy/cond.html @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + boost::capy::cond :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::cond

+
+
+
+

Portable error conditions for capy I/O operations.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/cond.hpp>

+
+
+
+
enum class cond : int;
+
+
+
+
+
+

Description

+
+
+

These are the conditions callers should compare against when handling errors from capy operations. The error enum values map to these conditions, as do platform‐specific error codes (e.g., ECANCELED, SSL EOF errors).

+
+
+
+
+

Example

+
+
+
+
auto [ec, n] = co_await stream.read_some( bufs );
+if( ec == cond::canceled )
+    // handle cancellation
+else if( ec == cond::eof )
+    // handle end of stream
+else if( ec )
+    // handle other errors
+
+
+
+
+
+

Members

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

eof

End‐of‐stream condition.

canceled

Operation cancelled condition.

stream_truncated

Stream truncated condition.

not_found

Item not found condition.

+
+
+
+

See Also

+
+
+

error

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer.html b/preview/reference/boost/capy/const_buffer.html new file mode 100644 index 0000000..125dd07 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer.html @@ -0,0 +1,573 @@ + + + + + + + + + + + + + + boost::capy::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer

+
+
+
+

A reference to a contiguous region of read‐only memory.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
class const_buffer
+    : public /* implementation-defined */
+
+
+
+
+
+

Description

+
+
+

Represents a pointer and size pair for a non‐modifiable byte range. Does not own the memory. Satisfies ConstBufferSequence (as a single‐element sequence). Implicitly constructible from mutable_buffer.

+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

/* implementation-defined */

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

const_buffer [constructor]

Constructors

operator=

Copy assignment.

data

Return a pointer to the memory region.

operator+=

Advance the buffer start, shrinking the region.

size

Return the size in bytes.

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::tag_invoke

Slice customization point for tag_invoke.

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

make_buffer

Return a buffer from a const std::array with a maximum size.

make_buffer

Return a buffer with a maximum size.

make_buffer

Return a buffer from a const std::span with a maximum size.

make_buffer

Return a buffer with a maximum size.

make_buffer

Return a buffer from a std::basic_string_view.

make_buffer

Return a buffer from a const std::vector.

make_buffer

Return a buffer from a const C‐style array.

make_buffer

Return a buffer from a std::basic_string_view with a maximum size.

make_buffer

Return a buffer from a const std::array.

make_buffer

Return a buffer.

make_buffer

Return a buffer from a const std::basic_string.

make_buffer

Return a buffer from a const contiguous range.

make_buffer

Return a buffer from a const std::span.

make_buffer

Return a buffer from a const contiguous range with a maximum size.

make_buffer

Return a buffer.

make_buffer

Return a buffer from a const C‐style array with a maximum size.

make_buffer

Return a buffer from a const std::vector with a maximum size.

make_buffer

Return a buffer from a const std::basic_string with a maximum size.

+
+
+
+

See Also

+
+
+

mutable_buffer, ConstBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/2constructor-03.html b/preview/reference/boost/capy/const_buffer/2constructor-03.html new file mode 100644 index 0000000..cdd095a --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/2constructor-03.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/2constructor-0460.html b/preview/reference/boost/capy/const_buffer/2constructor-0460.html new file mode 100644 index 0000000..546059f --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/2constructor-0460.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer::const_buffer

+
+
+
+

Construct from Asio buffer types.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<class ConstBuffer>
+requires (std::same_as<ConstBuffer, asio::const_buffer> ||
+                  std::same_as<ConstBuffer, asio::mutable_buffer>)
+constexpr
+const_buffer(ConstBuffer const& b) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

b

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/2constructor-0465.html b/preview/reference/boost/capy/const_buffer/2constructor-0465.html new file mode 100644 index 0000000..c540298 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/2constructor-0465.html @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer::const_buffer

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+

Construct an empty buffer.

+
+
+
+
constexpr
+const_buffer() = default;
+
+
+ +
+

Copy constructor.

+
+
+
+
constexpr
+const_buffer(const_buffer const& other) = default;
+
+
+ +
+

Construct from mutable_buffer.

+
+
+
+
constexpr
+const_buffer(mutable_buffer const& b) noexcept;
+
+
+ +
+

Construct from Asio buffer types.

+
+
+
+
template<class ConstBuffer>
+requires (std::same_as<ConstBuffer, asio::const_buffer> ||
+                  std::same_as<ConstBuffer, asio::mutable_buffer>)
+constexpr
+const_buffer(ConstBuffer const& b) noexcept;
+
+
+ +
+

Construct from pointer and size.

+
+
+
+
constexpr
+const_buffer(
+    void const* data,
+    std::size_t size) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/2constructor-07.html b/preview/reference/boost/capy/const_buffer/2constructor-07.html new file mode 100644 index 0000000..59628f6 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/2constructor-07.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/2constructor-0e.html b/preview/reference/boost/capy/const_buffer/2constructor-0e.html new file mode 100644 index 0000000..e50ab30 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/2constructor-0e.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/2constructor-0f.html b/preview/reference/boost/capy/const_buffer/2constructor-0f.html new file mode 100644 index 0000000..57f770c --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/2constructor-0f.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/data.html b/preview/reference/boost/capy/const_buffer/data.html new file mode 100644 index 0000000..cdd5f28 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/data.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/operator_assign.html b/preview/reference/boost/capy/const_buffer/operator_assign.html new file mode 100644 index 0000000..3182960 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/operator_assign.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/operator_plus_eq.html b/preview/reference/boost/capy/const_buffer/operator_plus_eq.html new file mode 100644 index 0000000..8cfa632 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/operator_plus_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::operator+= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer/size.html b/preview/reference/boost/capy/const_buffer/size.html new file mode 100644 index 0000000..de00843 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer/size.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::const_buffer::size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype.html b/preview/reference/boost/capy/const_buffer_archetype.html new file mode 100644 index 0000000..a14471d --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_.html b/preview/reference/boost/capy/const_buffer_archetype_.html new file mode 100644 index 0000000..f7fbf93 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_

+
+
+
+

Archetype for ConstBufferSequence concept checking.

+
+
+
+
+

Synopsis

+
+ +
+
+
struct const_buffer_archetype_;
+
+
+
+
+
+

Description

+
+
+

This type satisfies ConstBufferSequence but cannot be instantiated. Use it in concept definitions to verify that a function template accepts any ConstBufferSequence.

+
+
+
+
+

Example

+
+
+
+
template<typename T>
+concept MyWritable =
+    requires(T& stream, const_buffer_archetype buffers)
+    {
+        stream.write(buffers);
+    };
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

const_buffer_archetype_ [constructor] [deleted]

Constructors

operator=

Assignment operators

operator const_buffer

Conversion to const_buffer

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/2constructor-03.html b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-03.html new file mode 100644 index 0000000..d22aded --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-03.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::const_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_::const_buffer_archetype_

+
+
+
+

Copy constructor

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+const_buffer_archetype_(const_buffer_archetype_ const& other) = default;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/2constructor-05.html b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-05.html new file mode 100644 index 0000000..a48d439 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-05.html @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::const_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_::const_buffer_archetype_

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor

+
+
+
+
const_buffer_archetype_() = delete;
+
+
+ +
+

Copy constructor

+
+
+
+
constexpr
+const_buffer_archetype_(const_buffer_archetype_ const& other) = default;
+
+
+ +
+

Move constructor

+
+
+
+
constexpr
+const_buffer_archetype_(const_buffer_archetype_&& other) = default;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/2constructor-07.html b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-07.html new file mode 100644 index 0000000..c18dbf6 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-07.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::const_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/2constructor-0d.html b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-0d.html new file mode 100644 index 0000000..bf7f9e1 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/2constructor-0d.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::const_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_::const_buffer_archetype_

+
+
+
+

Move constructor

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+const_buffer_archetype_(const_buffer_archetype_&& other) = default;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/2conversion.html b/preview/reference/boost/capy/const_buffer_archetype_/2conversion.html new file mode 100644 index 0000000..9e433fd --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/2conversion.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::operator const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-00.html b/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-00.html new file mode 100644 index 0000000..51359fa --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-00.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_::operator=

+
+
+
+

Move assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+const_buffer_archetype_&
+operator=(const_buffer_archetype_&& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-02.html b/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-02.html new file mode 100644 index 0000000..a6a3fd0 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-02.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+const_buffer_archetype_&
+operator=(const_buffer_archetype_ const& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-07.html b/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-07.html new file mode 100644 index 0000000..46f303f --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_archetype_/operator_assign-07.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_archetype_::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::const_buffer_archetype_::operator=

+
+
+
+

Assignment operators

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
constexpr
+const_buffer_archetype_&
+operator=(const_buffer_archetype_ const& other) = default;
+
+
+ +
+

Move assignment operator

+
+
+
+
constexpr
+const_buffer_archetype_&
+operator=(const_buffer_archetype_&& other) = default;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_array.html b/preview/reference/boost/capy/const_buffer_array.html new file mode 100644 index 0000000..f7f149d --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_array.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_pair.html b/preview/reference/boost/capy/const_buffer_pair.html new file mode 100644 index 0000000..fef1bbc --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_pair.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_pair :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/const_buffer_param.html b/preview/reference/boost/capy/const_buffer_param.html new file mode 100644 index 0000000..1d52d00 --- /dev/null +++ b/preview/reference/boost/capy/const_buffer_param.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::const_buffer_param :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-06.html b/preview/reference/boost/capy/consuming_buffers-06.html new file mode 100644 index 0000000..02cc5b7 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-06.html @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers

+
+
+
+

Wrapper for consuming a buffer sequence incrementally.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class BufferSequence>
+requires MutableBufferSequence<BufferSequence> ||
+             ConstBufferSequence<BufferSequence>
+class consuming_buffers;
+
+
+
+
+
+

Description

+
+
+

This class wraps a buffer sequence and tracks the current position. It provides a consume(n) function that advances through the sequence as bytes are processed.

+
+
+

Works with both mutable and const buffer sequences.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

BufferSequence

The buffer sequence type.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c.html b/preview/reference/boost/capy/consuming_buffers-0c.html new file mode 100644 index 0000000..a4d5b30 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers

+
+
+
+

Wrapper for consuming a buffer sequence incrementally.

+
+
+
+
+

Synopsis

+
+ +
+
+
class consuming_buffers;
+
+
+
+
+
+

Description

+
+
+

This class wraps a buffer sequence and tracks the current position. It provides a consume(n) function that advances through the sequence as bytes are processed.

+
+
+

Works with both mutable and const buffer sequences.

+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

const_iterator

Iterator for the consuming buffer sequence.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

consuming_buffers [constructor]

Construct from a buffer sequence.

begin

Return iterator to beginning of remaining buffers.

consume

Consume n bytes from the buffer sequence.

end

Return iterator to end of buffer sequence.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

BufferSequence

The buffer sequence type.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/2constructor.html b/preview/reference/boost/capy/consuming_buffers-0c/2constructor.html new file mode 100644 index 0000000..1859a2e --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/2constructor.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::consuming_buffers :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/begin.html b/preview/reference/boost/capy/consuming_buffers-0c/begin.html new file mode 100644 index 0000000..e08488c --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/begin.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::begin :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator.html new file mode 100644 index 0000000..e7f3379 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator.html @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers::const_iterator

+
+
+
+

Iterator for the consuming buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
class const_iterator;
+
+
+
+
+
+

Description

+
+
+

Returns buffers starting from the current position, with the first buffer adjusted for consumed bytes.

+
+
+
+
+

Types

+
+ +++ + + + + + + + + + + + + + + + + + + + + +

Name

difference_type

iterator_category

pointer

reference

value_type

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

const_iterator [constructor]

Constructors

operator*

operator++

Increment operators

operator‐‐

Decrement operators

operator==

Equality operator

operator!=

Inequality operator

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-04.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-04.html new file mode 100644 index 0000000..ea9fbdc --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-04.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::const_iterator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-08.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-08.html new file mode 100644 index 0000000..1b81c4c --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-08.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::const_iterator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers::const_iterator::const_iterator

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor

+
+
+
+
const_iterator() noexcept = default;
+
+
+ +
+
+
const_iterator(
+    iterator_type it,
+    end_iterator_type end,
+    std::size_t consumed) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-0f.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-0f.html new file mode 100644 index 0000000..7fe57f1 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/2constructor-0f.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::const_iterator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/difference_type.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/difference_type.html new file mode 100644 index 0000000..0efe13e --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/difference_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::difference_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/iterator_category.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/iterator_category.html new file mode 100644 index 0000000..0852562 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/iterator_category.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::iterator_category :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-06.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-06.html new file mode 100644 index 0000000..8b415a6 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-06.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator‐‐ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-08.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-08.html new file mode 100644 index 0000000..430a196 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-08.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator‐‐ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers::const_iterator::operator‐‐

+
+
+
+

Decrement operators

+
+
+
+
+

Synopses

+
+ +
+

Decrement operator

+
+
+
+
const_iterator&
+operator‐‐() noexcept;
+
+
+ +
+

Decrement operator

+
+
+
+
const_iterator
+operator‐‐(int) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-0c.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-0c.html new file mode 100644 index 0000000..69c7bbd --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_dec-0c.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator‐‐ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_eq.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_eq.html new file mode 100644 index 0000000..dd1c219 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator== :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers::const_iterator::operator==

+
+
+
+

Equality operator

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator==(const_iterator const& other) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

true if the objects are equal, false otherwise

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-036.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-036.html new file mode 100644 index 0000000..1cc6ed6 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-036.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator++ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-03f.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-03f.html new file mode 100644 index 0000000..bf21f82 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-03f.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator++ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-0b.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-0b.html new file mode 100644 index 0000000..86a2dc7 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_inc-0b.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator++ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_not_eq.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_not_eq.html new file mode 100644 index 0000000..d5cfac4 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_not_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator!= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers::const_iterator::operator!=

+
+
+
+

Inequality operator

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator!=(const_iterator const& other) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

true if the objects are not equal, false otherwise

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_star.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_star.html new file mode 100644 index 0000000..86861b2 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/operator_star.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::operator* :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/pointer.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/pointer.html new file mode 100644 index 0000000..a8d9ff7 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/pointer.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::pointer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/reference.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/reference.html new file mode 100644 index 0000000..fcbdbdf --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/reference.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::reference :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/value_type.html b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/value_type.html new file mode 100644 index 0000000..8dee832 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/const_iterator/value_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::const_iterator::value_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/consume.html b/preview/reference/boost/capy/consuming_buffers-0c/consume.html new file mode 100644 index 0000000..7a69e06 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/consume.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::consuming_buffers::consume

+
+
+
+

Consume n bytes from the buffer sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+consume(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Advances the current position by n bytes, moving to the next buffer when the current one is exhausted.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to consume.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/consuming_buffers-0c/end.html b/preview/reference/boost/capy/consuming_buffers-0c/end.html new file mode 100644 index 0000000..eae45e2 --- /dev/null +++ b/preview/reference/boost/capy/consuming_buffers-0c/end.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::consuming_buffers::end :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/decomposes_to.html b/preview/reference/boost/capy/decomposes_to.html new file mode 100644 index 0000000..b47dad9 --- /dev/null +++ b/preview/reference/boost/capy/decomposes_to.html @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + boost::capy::decomposes_to :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::decomposes_to

+
+
+
+

Concept for types that decompose to a specific typelist.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    typename T,
+    typename... Types>
+concept decomposes_to = requires(T&& t) {
+    { detail::decomposed_types(std::forward<T>(t)) } ‐> std::same_as<std::tuple<Types...>>;
+};
+
+
+
+
+
+

Description

+
+
+

A type satisfies decomposes_to if it can be decomposed via structured bindings into the specified types. This includes aggregates with matching member types and tuple‐like types with matching element types.

+
+
+
+
+

Example

+
+
+
+
struct result { int a; double b; };
+
+static_assert(decomposes_to<result, int, double>);
+static_assert(decomposes_to<std::tuple<int, double>, int, double>);
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

T

The type to decompose.

Types

The expected element types after decomposition.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/dynamic_buffer-07.html b/preview/reference/boost/capy/dynamic_buffer-07.html new file mode 100644 index 0000000..6c227de --- /dev/null +++ b/preview/reference/boost/capy/dynamic_buffer-07.html @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + boost::capy::dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::dynamic_buffer

+
+
+
+

Create a dynamic buffer from a string.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+basic_string_dynamic_buffer<CharT, Traits, Allocator>
+dynamic_buffer(
+    std::basic_string<CharT, Traits, Allocator>& s,
+    std::size_t max_size = std::size_t(‐1));
+
+
+
+
+
+

Return Value

+
+
+

A string_dynamic_buffer wrapping the string.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

s

The string to wrap.

max_size

Optional maximum size limit.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/dynamic_buffer-0d.html b/preview/reference/boost/capy/dynamic_buffer-0d.html new file mode 100644 index 0000000..8c46829 --- /dev/null +++ b/preview/reference/boost/capy/dynamic_buffer-0d.html @@ -0,0 +1,461 @@ + + + + + + + + + + + + + + boost::capy::dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::dynamic_buffer

+
+
+
+

dynamic_buffer overloads

+
+
+
+
+

Synopses

+
+ +
+

Create a dynamic buffer from a vector.

+
+
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_fundamental_v<T> && (sizeof(T) == 1)
+basic_vector_dynamic_buffer<T, Allocator>
+dynamic_buffer(
+    std::vector<T, Allocator>& v,
+    std::size_t max_size = std::size_t(‐1));
+
+
+ +
+

Create a dynamic buffer from a string.

+
+
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+basic_string_dynamic_buffer<CharT, Traits, Allocator>
+dynamic_buffer(
+    std::basic_string<CharT, Traits, Allocator>& s,
+    std::size_t max_size = std::size_t(‐1));
+
+
+ +
+
+
+

Return Value

+
+
+
    +
  • +

    A vector_dynamic_buffer wrapping the vector.

    +
  • +
  • +

    A string_dynamic_buffer wrapping the string.

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

v

The vector to wrap. Element type must be a fundamental type with sizeof 1.

max_size

Optional maximum size limit.

s

The string to wrap.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/dynamic_buffer-0f.html b/preview/reference/boost/capy/dynamic_buffer-0f.html new file mode 100644 index 0000000..6b0109d --- /dev/null +++ b/preview/reference/boost/capy/dynamic_buffer-0f.html @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + boost::capy::dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::dynamic_buffer

+
+
+
+

Create a dynamic buffer from a vector.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_fundamental_v<T> && (sizeof(T) == 1)
+basic_vector_dynamic_buffer<T, Allocator>
+dynamic_buffer(
+    std::vector<T, Allocator>& v,
+    std::size_t max_size = std::size_t(‐1));
+
+
+
+
+
+

Return Value

+
+
+

A vector_dynamic_buffer wrapping the vector.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

v

The vector to wrap. Element type must be a fundamental type with sizeof 1.

max_size

Optional maximum size limit.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/end.html b/preview/reference/boost/capy/end.html new file mode 100644 index 0000000..f2e3112 --- /dev/null +++ b/preview/reference/boost/capy/end.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::end :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/end_mrdocs_workaround_t.html b/preview/reference/boost/capy/end_mrdocs_workaround_t.html new file mode 100644 index 0000000..6c09dda --- /dev/null +++ b/preview/reference/boost/capy/end_mrdocs_workaround_t.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::end_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::end_mrdocs_workaround_t

+
+
+
+

Return an iterator past the last buffer in a sequence.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
struct end_mrdocs_workaround_t;
+
+
+
+
+
+

Description

+
+
+

Handles single buffers and ranges uniformly. For a single buffer, returns a pointer one past it.

+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

operator()

Function call operators

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-09.html b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-09.html new file mode 100644 index 0000000..9611196 --- /dev/null +++ b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-09.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + boost::capy::end_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::end_mrdocs_workaround_t::operator()

+
+
+
+

Function call operators

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<ConstBufferSequence BS>
+requires (!std::convertible_to<BS, const_buffer>)
+auto
+operator()(BS& bs) const noexcept;
+
+
+ +
+
+
template<ConstBufferSequence BS>
+requires (!std::convertible_to<BS, const_buffer>)
+auto
+operator()(BS const& bs) const noexcept;
+
+
+ +
+
+
template<std::convertible_to<const_buffer> ConvertibleToBuffer>
+ConvertibleToBuffer const*
+operator()(ConvertibleToBuffer const& b) const noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0c.html b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0c.html new file mode 100644 index 0000000..0c43078 --- /dev/null +++ b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0c.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::end_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0f6.html b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0f6.html new file mode 100644 index 0000000..5c0333a --- /dev/null +++ b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0f6.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + boost::capy::end_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0fa.html b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0fa.html new file mode 100644 index 0000000..976d6a3 --- /dev/null +++ b/preview/reference/boost/capy/end_mrdocs_workaround_t/operator_call-0fa.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::end_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/error.html b/preview/reference/boost/capy/error.html new file mode 100644 index 0000000..bd9c804 --- /dev/null +++ b/preview/reference/boost/capy/error.html @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + boost::capy::error :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::error

+
+
+
+

Error codes for capy I/O operations.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/error.hpp>

+
+
+
+
enum class error : int;
+
+
+
+
+
+

Description

+
+
+

These codes are produced by capy algorithms and I/O operations.

+
+
+ + + + + +
+ + +
+

Callers must never compare received error_code values directly against this enum. Always compare against the portable cond error conditions instead. These enum values are implementation details subject to change.

+
+
+
+
+
+
+

Members

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

eof

End‐of‐stream reached. Compare with cond::eof.

canceled

Operation was cancelled. Compare with cond::canceled.

test_failure

Internal test assertion failed.

stream_truncated

Peer closed connection without proper TLS shutdown. Compare with cond::stream_truncated.

not_found

Requested item was not found. Compare with cond::not_found.

+
+
+
+

See Also

+
+
+

cond

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context.html b/preview/reference/boost/capy/execution_context.html new file mode 100644 index 0000000..55a4608 --- /dev/null +++ b/preview/reference/boost/capy/execution_context.html @@ -0,0 +1,585 @@ + + + + + + + + + + + + + + boost::capy::execution_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context

+
+
+
+

Base class for I/O object containers providing service management.

+
+
+
+
+

Synopsis

+
+ +
+
+
class execution_context;
+
+
+
+
+
+

Description

+
+
+

An execution context represents a place where function objects are executed. It provides a service registry where polymorphic services can be stored and retrieved by type. Each service type may be stored at most once. Services may specify a nested key_type to enable lookup by a base class type.

+
+
+

Derived classes such as io_context extend this to provide execution facilities like event loops and thread pools. Derived class destructors must call shutdown() and destroy() to ensure proper service cleanup before member destruction.

+
+
+
+
+

Service Lifecycle

+
+
+

Services are created on first use via use_service() or explicitly via make_service(). During destruction, shutdown() is called on each service in reverse order of creation, then destroy() deletes them. Both functions are idempotent.

+
+
+
+
+

Thread Safety

+
+
+

Service registration and lookup functions are thread‐safe. The shutdown() and destroy() functions are not thread‐safe and must only be called during destruction.

+
+
+
+
+

Example

+
+
+
+
struct file_service : execution_context::service
+{
+protected:
+    void shutdown() override {}
+};
+
+struct posix_file_service : file_service
+{
+    using key_type = file_service;
+
+    explicit posix_file_service(execution_context&) {}
+};
+
+class io_context : public execution_context
+{
+public:
+    ~io_context()
+    {
+        shutdown();
+        destroy();
+    }
+};
+
+io_context ctx;
+ctx.make_service<posix_file_service>();
+ctx.find_service<file_service>();       // returns posix_file_service*
+ctx.find_service<posix_file_service>(); // also works
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

service

Abstract base class for services owned by an execution context.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

execution_context [constructor]

Default constructor.

~execution_context [destructor]

Destructor.

operator= [deleted]

Copy assignment operator

find_service

Return a pointer to the service of type T, or nullptr.

get_frame_allocator

Return the memory resource used for coroutine frame allocation.

has_service

Return true if a service of type T exists.

make_service

Construct and add a service.

set_frame_allocator

set_frame_allocator overloads

target

Return a pointer to this context if it matches the requested type.

use_service

Return a reference to the service of type T, creating it if needed.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

execution_context [constructor]

Construct from Derived

destroy

Destroy all services.

shutdown

Shut down all services.

+
+
+
+

Derived Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

thread_pool

A pool of threads for executing work concurrently.

+
+
+
+

See Also

+
+
+

service, is_execution_context

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/2constructor-04.html b/preview/reference/boost/capy/execution_context/2constructor-04.html new file mode 100644 index 0000000..48373a1 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/2constructor-04.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::execution_context::execution_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/2constructor-05.html b/preview/reference/boost/capy/execution_context/2constructor-05.html new file mode 100644 index 0000000..fe270b3 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/2constructor-05.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::execution_context::execution_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/2constructor-0d1.html b/preview/reference/boost/capy/execution_context/2constructor-0d1.html new file mode 100644 index 0000000..cd2cdc5 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/2constructor-0d1.html @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + boost::capy::execution_context::execution_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/2constructor-0d8.html b/preview/reference/boost/capy/execution_context/2constructor-0d8.html new file mode 100644 index 0000000..d17949a --- /dev/null +++ b/preview/reference/boost/capy/execution_context/2constructor-0d8.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::execution_context::execution_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/2destructor.html b/preview/reference/boost/capy/execution_context/2destructor.html new file mode 100644 index 0000000..ddbef4c --- /dev/null +++ b/preview/reference/boost/capy/execution_context/2destructor.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::execution_context::~execution_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::~execution_context

+
+
+
+

Destructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
~execution_context();
+
+
+
+
+
+

Description

+
+
+

Calls shutdown() then destroy() to clean up all services.

+
+
+
+
+

Effects

+
+
+

All services are shut down and deleted in reverse order of creation.

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/destroy.html b/preview/reference/boost/capy/execution_context/destroy.html new file mode 100644 index 0000000..e479328 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/destroy.html @@ -0,0 +1,441 @@ + + + + + + + + + + + + + + boost::capy::execution_context::destroy :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::destroy

+
+
+
+

Destroy all services.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+destroy() noexcept;
+
+
+
+
+
+

Description

+
+
+

Deletes all services in reverse order of creation. Derived classes should call this as the final step of destruction. This function is idempotent; subsequent calls have no effect.

+
+
+
+
+

Preconditions

+
+
+
    +
  • +

    `shutdown()` has been called.

    +
  • +
+
+
+
+
+

Effects

+
+
+

All services are deleted and removed from the container.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    The service container is empty.

    +
  • +
+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Must not be called concurrently with other operations on this execution_context.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/find_service.html b/preview/reference/boost/capy/execution_context/find_service.html new file mode 100644 index 0000000..e074591 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/find_service.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::execution_context::find_service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::find_service

+
+
+
+

Return a pointer to the service of type T, or nullptr.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class T>
+T*
+find_service() const noexcept;
+
+
+
+
+
+

Thread Safety

+
+
+

Thread‐safe.

+
+
+
+
+

Return Value

+
+
+

A pointer to the service, or nullptr if not present.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The type of service to find.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/get_frame_allocator.html b/preview/reference/boost/capy/execution_context/get_frame_allocator.html new file mode 100644 index 0000000..54925a7 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/get_frame_allocator.html @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + boost::capy::execution_context::get_frame_allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::get_frame_allocator

+
+
+
+

Return the memory resource used for coroutine frame allocation.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::pmr::memory_resource*
+get_frame_allocator() const noexcept;
+
+
+
+
+
+

Description

+
+
+

The returned pointer is valid for the lifetime of this context. By default, this returns a pointer to the recycling memory resource which pools frame allocations for reuse.

+
+
+
+
+

Return Value

+
+
+

Pointer to the frame allocator.

+
+
+
+
+

See Also

+
+
+

set_frame_allocator

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/has_service.html b/preview/reference/boost/capy/execution_context/has_service.html new file mode 100644 index 0000000..1faabdd --- /dev/null +++ b/preview/reference/boost/capy/execution_context/has_service.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::execution_context::has_service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::has_service

+
+
+
+

Return true if a service of type T exists.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class T>
+bool
+has_service() const noexcept;
+
+
+
+
+
+

Thread Safety

+
+
+

Thread‐safe.

+
+
+
+
+

Return Value

+
+
+

true if the service exists.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The type of service to check.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/make_service.html b/preview/reference/boost/capy/execution_context/make_service.html new file mode 100644 index 0000000..52ce2f9 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/make_service.html @@ -0,0 +1,505 @@ + + + + + + + + + + + + + + boost::capy::execution_context::make_service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::make_service

+
+
+
+

Construct and add a service.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class... Args>
+T&
+make_service(Args&&... args);
+
+
+
+
+
+

Description

+
+
+

A new service of type T is constructed using the provided arguments and added to the container. If T has a nested key_type, the service is also indexed under that type.

+
+
+
+
+

Constraints

+
+
+
    +
  • +

    `T` must derive from `service`.

    +
  • +
  • +

    `T` must be constructible from `execution_context&, Args...`.

    +
  • +
  • +

    If `T::key_type` exists, `T&` must be convertible to `key_type&`.

    +
  • +
+
+
+
+
+

Exception Safety

+
+
+

Strong guarantee. If service creation throws, the container is unchanged.

+
+
+
+
+

Thread Safety

+
+
+

Thread‐safe.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if a service of the same type or key_type already exists.

+
+
+
+

Return Value

+
+
+

A reference to the created service.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The type of service to create.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

args

Arguments forwarded to the constructor of T.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/operator_assign.html b/preview/reference/boost/capy/execution_context/operator_assign.html new file mode 100644 index 0000000..95b4e69 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::execution_context::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
execution_context&
+operator=(execution_context const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/service.html b/preview/reference/boost/capy/execution_context/service.html new file mode 100644 index 0000000..921347a --- /dev/null +++ b/preview/reference/boost/capy/execution_context/service.html @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + boost::capy::execution_context::service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::service

+
+
+
+

Abstract base class for services owned by an execution context.

+
+
+
+
+

Synopsis

+
+ +
+
+
class service;
+
+
+
+
+
+

Description

+
+
+

Services provide extensible functionality to an execution context. Each service type can be registered at most once. Services are created via use_service() or make_service() and are owned by the execution context for their lifetime.

+
+
+

Derived classes must implement the pure virtual shutdown() member function, which is called when the owning execution context is being destroyed. The shutdown() function should release resources and cancel outstanding operations without blocking.

+
+
+
+
+

Deriving from service

+
+
+
    +
  • +

    Implement `shutdown()` to perform cleanup.

    +
  • +
  • +

    Accept `execution_context&` as the first constructor parameter.

    +
  • +
  • +

    Optionally define `key_type` to enable base‐class lookup.

    +
  • +
+
+
+
+
+

Example

+
+
+
+
struct my_service : execution_context::service
+{
+    explicit my_service(execution_context&) {}
+
+protected:
+    void shutdown() override
+    {
+        // Cancel pending operations, release resources
+    }
+};
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

~service [destructor] [virtual]

Destructor

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

service [constructor]

Default constructor

shutdown [virtual]

Called when the owning execution context shuts down.

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::execution_context

Base class for I/O object containers providing service management.

+
+
+
+

See Also

+
+
+

execution_context

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/service/2constructor.html b/preview/reference/boost/capy/execution_context/service/2constructor.html new file mode 100644 index 0000000..1316256 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/service/2constructor.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::execution_context::service::service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/service/2destructor.html b/preview/reference/boost/capy/execution_context/service/2destructor.html new file mode 100644 index 0000000..04af3f9 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/service/2destructor.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + boost::capy::execution_context::service::~service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/service/shutdown.html b/preview/reference/boost/capy/execution_context/service/shutdown.html new file mode 100644 index 0000000..c553d8e --- /dev/null +++ b/preview/reference/boost/capy/execution_context/service/shutdown.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::execution_context::service::shutdown :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::service::shutdown

+
+
+
+

Called when the owning execution context shuts down.

+
+
+
+
+

Synopsis

+
+ +
+
+
virtual
+void
+shutdown() = 0;
+
+
+
+
+
+

Description

+
+
+

Implementations should release resources and cancel any outstanding asynchronous operations. This function must not block and must not throw exceptions. Services are shut down in reverse order of creation.

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/set_frame_allocator-00.html b/preview/reference/boost/capy/execution_context/set_frame_allocator-00.html new file mode 100644 index 0000000..b0c95ff --- /dev/null +++ b/preview/reference/boost/capy/execution_context/set_frame_allocator-00.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::execution_context::set_frame_allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::set_frame_allocator

+
+
+
+

Set the memory resource used for coroutine frame allocation.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+set_frame_allocator(std::pmr::memory_resource* mr) noexcept;
+
+
+
+
+
+

Description

+
+
+

The caller is responsible for ensuring the memory resource remains valid for the lifetime of all coroutines launched using this context's executor.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Must not be called while any thread may be referencing this execution context or its executor.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

mr

Pointer to the memory resource.

+
+
+
+

See Also

+
+
+

get_frame_allocator

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/set_frame_allocator-07.html b/preview/reference/boost/capy/execution_context/set_frame_allocator-07.html new file mode 100644 index 0000000..58484cb --- /dev/null +++ b/preview/reference/boost/capy/execution_context/set_frame_allocator-07.html @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + boost::capy::execution_context::set_frame_allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::set_frame_allocator

+
+
+
+

Set the frame allocator from a standard Allocator.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class Allocator>
+requires (!std::is_pointer_v<Allocator>)
+void
+set_frame_allocator(Allocator const& a);
+
+
+
+
+
+

Description

+
+
+

The allocator is wrapped in an internal memory resource adapter owned by this context. The wrapper remains valid for the lifetime of this context or until a subsequent call to set_frame_allocator.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Must not be called while any thread may be referencing this execution context or its executor.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Allocator

The allocator type satisfying the standard Allocator requirements.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

a

The allocator to use.

+
+
+
+

See Also

+
+
+

get_frame_allocator

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/set_frame_allocator-09.html b/preview/reference/boost/capy/execution_context/set_frame_allocator-09.html new file mode 100644 index 0000000..126c378 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/set_frame_allocator-09.html @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + boost::capy::execution_context::set_frame_allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::set_frame_allocator

+
+
+
+

set_frame_allocator overloads

+
+
+
+
+

Synopses

+
+ +
+

Set the memory resource used for coroutine frame allocation.

+
+
+
+
void
+set_frame_allocator(std::pmr::memory_resource* mr) noexcept;
+
+
+ +
+

Set the frame allocator from a standard Allocator.

+
+
+
+
template<class Allocator>
+requires (!std::is_pointer_v<Allocator>)
+void
+set_frame_allocator(Allocator const& a);
+
+
+ +
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Allocator

The allocator type satisfying the standard Allocator requirements.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

mr

Pointer to the memory resource.

a

The allocator to use.

+
+
+
+

See Also

+
+
+

get_frame_allocator

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/shutdown.html b/preview/reference/boost/capy/execution_context/shutdown.html new file mode 100644 index 0000000..26ca404 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/shutdown.html @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + boost::capy::execution_context::shutdown :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::shutdown

+
+
+
+

Shut down all services.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+shutdown() noexcept;
+
+
+
+
+
+

Description

+
+
+

Calls shutdown() on each service in reverse order of creation. After this call, services remain allocated but are in a stopped state. Derived classes should call this in their destructor before any members are destroyed. This function is idempotent; subsequent calls have no effect.

+
+
+
+
+

Effects

+
+
+

Each service's shutdown() member function is invoked once.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    All services are in a stopped state.

    +
  • +
+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Thread Safety

+
+
+

Not thread‐safe. Must not be called concurrently with other operations on this execution_context.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/target-07.html b/preview/reference/boost/capy/execution_context/target-07.html new file mode 100644 index 0000000..fa80e84 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/target-07.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::execution_context::target :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::target

+
+
+
+

Return a pointer to this context if it matches the requested type.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename ExecutionContext>
+ExecutionContext*
+target();
+
+
+
+
+
+

Description

+
+
+

Performs a type check and downcasts this when the types match, or returns nullptr otherwise. Analogous to std::any_cast< ExecutionContext >( &a ).

+
+
+
+
+

Return Value

+
+
+

A pointer to this context as the requested type, or nullptr if the type does not match.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ExecutionContext

The derived context type to retrieve.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/target-0b.html b/preview/reference/boost/capy/execution_context/target-0b.html new file mode 100644 index 0000000..3b9b081 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/target-0b.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::execution_context::target :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::target

+
+
+
+

Return a pointer to this context if it matches the requested type.

+
+
+
+
+

Synopses

+
+ +
+

Return a pointer to this context if it matches the requested type.

+
+
+
+
template<typename ExecutionContext>
+ExecutionContext const*
+target() const;
+
+
+ +
+

Return a pointer to this context if it matches the requested type.

+
+
+
+
template<typename ExecutionContext>
+ExecutionContext*
+target();
+
+
+ +
+
+
+

Return Value

+
+
+

A pointer to this context as the requested type, or nullptr if the type does not match.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ExecutionContext

The derived context type to retrieve.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/target-0e.html b/preview/reference/boost/capy/execution_context/target-0e.html new file mode 100644 index 0000000..11ad7ff --- /dev/null +++ b/preview/reference/boost/capy/execution_context/target-0e.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::execution_context::target :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::target

+
+
+
+

Return a pointer to this context if it matches the requested type.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename ExecutionContext>
+ExecutionContext const*
+target() const;
+
+
+
+
+
+

Description

+
+
+

Performs a type check and downcasts this when the types match, or returns nullptr otherwise. Analogous to std::any_cast< ExecutionContext >( &a ).

+
+
+
+
+

Return Value

+
+
+

A pointer to this context as the requested type, or nullptr if the type does not match.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ExecutionContext

The derived context type to retrieve.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/execution_context/use_service.html b/preview/reference/boost/capy/execution_context/use_service.html new file mode 100644 index 0000000..92e6ed5 --- /dev/null +++ b/preview/reference/boost/capy/execution_context/use_service.html @@ -0,0 +1,456 @@ + + + + + + + + + + + + + + boost::capy::execution_context::use_service :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::execution_context::use_service

+
+
+
+

Return a reference to the service of type T, creating it if needed.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<class T>
+T&
+use_service();
+
+
+
+
+
+

Description

+
+
+

If no service of type T exists, one is created by calling T(execution_context&). If T has a nested key_type, the service is also indexed under that type.

+
+
+
+
+

Constraints

+
+
+
    +
  • +

    `T` must derive from `service`.

    +
  • +
  • +

    `T` must be constructible from `execution_context&`.

    +
  • +
+
+
+
+
+

Exception Safety

+
+
+

Strong guarantee. If service creation throws, the container is unchanged.

+
+
+
+
+

Thread Safety

+
+
+

Thread‐safe.

+
+
+
+
+

Return Value

+
+
+

A reference to the service.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The type of service to retrieve or create.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref.html b/preview/reference/boost/capy/executor_ref.html new file mode 100644 index 0000000..a3f6a07 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref.html @@ -0,0 +1,498 @@ + + + + + + + + + + + + + + boost::capy::executor_ref :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref

+
+
+
+

A type‐erased reference wrapper for executor objects.

+
+
+
+
+

Synopsis

+
+ +
+
+
class executor_ref;
+
+
+
+
+
+

Description

+
+
+

This class provides type erasure for any executor type, enabling runtime polymorphism without virtual functions or allocation. It stores a pointer to the original executor and a pointer to a static vtable, allowing executors of different types to be stored uniformly while satisfying the full Executor concept.

+
+
+
+
+

Reference Semantics

+
+
+

This class has reference semantics: it does not allocate or own the wrapped executor. Copy operations simply copy the internal pointers. The caller must ensure the referenced executor outlives all executor_ref instances that wrap it.

+
+
+
+
+

Thread Safety

+
+
+

The executor_ref itself is not thread‐safe for concurrent modification, but its executor operations are safe to call concurrently if the underlying executor supports it.

+
+
+
+
+

Executor Concept

+
+
+

This class satisfies the Executor concept, making it usable anywhere a concrete executor is expected.

+
+
+
+
+

Example

+
+
+
+
void store_executor(executor_ref ex)
+{
+    if(ex)
+        ex.post(my_coroutine);
+}
+
+io_context ctx;
+store_executor(ctx.get_executor());
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

executor_ref [constructor]

Constructors

operator=

Copy assignment operator.

context

Returns a reference to the associated execution context.

dispatch

Dispatches a coroutine handle through the wrapped executor.

on_work_finished

Informs the executor that work has completed.

on_work_started

Informs the executor that work is beginning.

post

Posts a coroutine handle to the wrapped executor.

target

Return a pointer to the wrapped executor if it matches the requested type.

operator bool

Returns true if this instance holds a valid executor.

operator==

Compares two executor references for equality.

+
+
+
+

See Also

+
+
+

any_executor, Executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/2constructor-01.html b/preview/reference/boost/capy/executor_ref/2constructor-01.html new file mode 100644 index 0000000..803ccb3 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/2constructor-01.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::executor_ref :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::executor_ref

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor.

+
+
+
+
constexpr
+executor_ref() = default;
+
+
+ +
+

Copy constructor.

+
+
+
+
constexpr
+executor_ref(executor_ref const& other) = default;
+
+
+ +
+

Construct from Ex

+
+
+
+
template<class Ex>
+requires (!std::same_as<std::decay_t<Ex>, executor_ref>)
+executor_ref(Ex const& ex) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/2constructor-04.html b/preview/reference/boost/capy/executor_ref/2constructor-04.html new file mode 100644 index 0000000..4fd9a82 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/2constructor-04.html @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::executor_ref :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/2constructor-0b.html b/preview/reference/boost/capy/executor_ref/2constructor-0b.html new file mode 100644 index 0000000..4028fe3 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/2constructor-0b.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::executor_ref :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/2constructor-0c.html b/preview/reference/boost/capy/executor_ref/2constructor-0c.html new file mode 100644 index 0000000..7d06207 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/2constructor-0c.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::executor_ref :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::executor_ref

+
+
+
+

Copy constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+executor_ref(executor_ref const& other) = default;
+
+
+
+
+
+

Description

+
+
+

Copies the internal pointers, preserving identity. This enables the same‐executor optimization when passing executor_ref through coroutine chains.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/2conversion.html b/preview/reference/boost/capy/executor_ref/2conversion.html new file mode 100644 index 0000000..b99970f --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/2conversion.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::operator bool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/context.html b/preview/reference/boost/capy/executor_ref/context.html new file mode 100644 index 0000000..7e471a3 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/context.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/dispatch.html b/preview/reference/boost/capy/executor_ref/dispatch.html new file mode 100644 index 0000000..2d4a712 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/dispatch.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::dispatch :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::dispatch

+
+
+
+

Dispatches a coroutine handle through the wrapped executor.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+dispatch(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

Returns a handle for symmetric transfer. If running in the executor's thread, returns h. Otherwise, posts the coroutine for later execution and returns std::noop_coroutine().

+
+
+
+
+

Return Value

+
+
+

A handle for symmetric transfer or std::noop_coroutine().

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to dispatch for resumption.

+
+
+
+

Preconditions

+
+
+
    +
  • +

    This instance was constructed with a valid executor.

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/on_work_finished.html b/preview/reference/boost/capy/executor_ref/on_work_finished.html new file mode 100644 index 0000000..30465e9 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/on_work_finished.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::on_work_finished :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/on_work_started.html b/preview/reference/boost/capy/executor_ref/on_work_started.html new file mode 100644 index 0000000..3ce38ca --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/on_work_started.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::on_work_started :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::on_work_started

+
+
+
+

Informs the executor that work is beginning.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+on_work_started() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Must be paired with a subsequent call to on_work_finished().

+
+
+
+
+

Preconditions

+
+
+
    +
  • +

    This instance was constructed with a valid executor.

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/operator_assign.html b/preview/reference/boost/capy/executor_ref/operator_assign.html new file mode 100644 index 0000000..7bbeace --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/operator_assign.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::operator=

+
+
+
+

Copy assignment operator.

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+executor_ref&
+operator=(executor_ref const& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/operator_eq.html b/preview/reference/boost/capy/executor_ref/operator_eq.html new file mode 100644 index 0000000..a098dba --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/operator_eq.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::operator== :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::operator==

+
+
+
+

Compares two executor references for equality.

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator==(executor_ref const& other) const noexcept;
+
+
+
+
+
+

Description

+
+
+

Two executor_ref instances are equal if they wrap executors of the same type that compare equal.

+
+
+
+
+

Return Value

+
+
+

true if both wrap equal executors of the same type.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The executor reference to compare against.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/post.html b/preview/reference/boost/capy/executor_ref/post.html new file mode 100644 index 0000000..042f409 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/post.html @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::post :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::post

+
+
+
+

Posts a coroutine handle to the wrapped executor.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+post(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

Posts the coroutine handle to the executor for later execution and returns. The caller should transfer to std::noop_coroutine() after calling this.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to post for resumption.

+
+
+
+

Preconditions

+
+
+
    +
  • +

    This instance was constructed with a valid executor.

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/target-00.html b/preview/reference/boost/capy/executor_ref/target-00.html new file mode 100644 index 0000000..85d8650 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/target-00.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::target :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::target

+
+
+
+

Return a pointer to the wrapped executor if it matches the requested type.

+
+
+
+
+

Synopses

+
+ +
+

Return a pointer to the wrapped executor if it matches the requested type.

+
+
+
+
template<typename Executor>
+Executor const*
+target() const;
+
+
+ +
+

Return a pointer to the wrapped executor if it matches the requested type.

+
+
+
+
template<typename Executor>
+Executor*
+target();
+
+
+ +
+
+
+

Return Value

+
+
+

A pointer to the underlying executor, or nullptr if the type does not match.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Executor

The executor type to retrieve.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/target-04.html b/preview/reference/boost/capy/executor_ref/target-04.html new file mode 100644 index 0000000..e3a3df9 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/target-04.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::target :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::target

+
+
+
+

Return a pointer to the wrapped executor if it matches the requested type.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename Executor>
+Executor const*
+target() const;
+
+
+
+
+
+

Description

+
+
+

Performs a type check against the stored executor and returns a typed pointer when the types match, or nullptr otherwise. Analogous to std::any_cast< Executor >( &a ).

+
+
+
+
+

Return Value

+
+
+

A pointer to the underlying executor, or nullptr if the type does not match.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Executor

The executor type to retrieve.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/executor_ref/target-0c.html b/preview/reference/boost/capy/executor_ref/target-0c.html new file mode 100644 index 0000000..1bd9559 --- /dev/null +++ b/preview/reference/boost/capy/executor_ref/target-0c.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::executor_ref::target :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::executor_ref::target

+
+
+
+

Return a pointer to the wrapped executor if it matches the requested type.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename Executor>
+Executor*
+target();
+
+
+
+
+
+

Description

+
+
+

Performs a type check against the stored executor and returns a typed pointer when the types match, or nullptr otherwise. Analogous to std::any_cast< Executor >( &a ).

+
+
+
+
+

Return Value

+
+
+

A pointer to the underlying executor, or nullptr if the type does not match.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Executor

The executor type to retrieve.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer.html b/preview/reference/boost/capy/flat_dynamic_buffer.html new file mode 100644 index 0000000..bb76db4 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer.html @@ -0,0 +1,511 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer

+
+
+
+

A fixed‐capacity linear buffer satisfying DynamicBuffer.

+
+
+
+
+

Synopsis

+
+ +
+
+
class flat_dynamic_buffer;
+
+
+
+
+
+

Description

+
+
+

This class provides a contiguous buffer with fixed capacity determined at construction. Buffer sequences returned from data and prepare always contain exactly one element, making it suitable for APIs requiring contiguous memory.

+
+
+
+
+

Example

+
+
+
+
char storage[1024];
+flat_dynamic_buffer fb( storage, sizeof( storage ) );
+
+// Write data
+auto mb = fb.prepare( 100 );
+std::memcpy( mb.data(), "hello", 5 );
+fb.commit( 5 );
+
+// Read data
+auto data = fb.data();
+// process data...
+fb.consume( 5 );
+
+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Unsafe.

+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

const_buffers_type

The ConstBufferSequence type for readable bytes.

is_dynamic_buffer_adapter

Indicates this is a DynamicBuffer adapter over external storage.

mutable_buffers_type

The MutableBufferSequence type for writable bytes.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

flat_dynamic_buffer [constructor]

Constructors

operator=

Copy assignment.

capacity

Return the number of writable bytes without reallocation.

commit

Move bytes from the output to the input sequence.

consume

Remove bytes from the beginning of the input sequence.

data

Return a buffer sequence representing the readable bytes.

max_size

Return the maximum number of bytes the buffer can hold.

prepare

Return a buffer sequence for writing.

size

Return the number of readable bytes.

+
+
+
+

See Also

+
+
+

circular_dynamic_buffer, string_dynamic_buffer

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-00.html b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-00.html new file mode 100644 index 0000000..cec1b8b --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-00.html @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::flat_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer::flat_dynamic_buffer

+
+
+
+

Construct a flat buffer over existing storage.

+
+
+
+
+

Synopsis

+
+ +
+
+
flat_dynamic_buffer(
+    void* data,
+    std::size_t capacity,
+    std::size_t initial_size = 0);
+
+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if initial_size > capacity.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

data

Pointer to the storage.

capacity

Size of the storage in bytes.

initial_size

Number of bytes already present as readable. Must not exceed capacity.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-05.html b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-05.html new file mode 100644 index 0000000..c5080ea --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-05.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::flat_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-07.html b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-07.html new file mode 100644 index 0000000..bceccf5 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-07.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::flat_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-0c.html b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-0c.html new file mode 100644 index 0000000..e6a2b1e --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/2constructor-0c.html @@ -0,0 +1,469 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::flat_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer::flat_dynamic_buffer

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Construct an empty flat buffer with zero capacity.

+
+
+
+
constexpr
+flat_dynamic_buffer() = default;
+
+
+ +
+

Copy constructor.

+
+
+
+
constexpr
+flat_dynamic_buffer(flat_dynamic_buffer const& other) = default;
+
+
+ +
+

Construct a flat buffer over existing storage.

+
+
+
+
flat_dynamic_buffer(
+    void* data,
+    std::size_t capacity,
+    std::size_t initial_size = 0);
+
+
+ +
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if initial_size > capacity.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

data

Pointer to the storage.

capacity

Size of the storage in bytes.

initial_size

Number of bytes already present as readable. Must not exceed capacity.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/capacity.html b/preview/reference/boost/capy/flat_dynamic_buffer/capacity.html new file mode 100644 index 0000000..42721c4 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/capacity.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::capacity :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/commit.html b/preview/reference/boost/capy/flat_dynamic_buffer/commit.html new file mode 100644 index 0000000..b011848 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/commit.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::commit :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer::commit

+
+
+
+

Move bytes from the output to the input sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+commit(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from prepare. Buffer sequences from data remain valid.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to commit. If greater than the prepared size, all prepared bytes are committed.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/const_buffers_type.html b/preview/reference/boost/capy/flat_dynamic_buffer/const_buffers_type.html new file mode 100644 index 0000000..50bf1db --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/const_buffers_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::const_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/consume.html b/preview/reference/boost/capy/flat_dynamic_buffer/consume.html new file mode 100644 index 0000000..a8f8ed4 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/consume.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::consume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer::consume

+
+
+
+

Remove bytes from the beginning of the input sequence.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+consume(std::size_t n) noexcept;
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from data. Buffer sequences from prepare remain valid.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The number of bytes to consume. If greater than size(), all readable bytes are consumed.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/data.html b/preview/reference/boost/capy/flat_dynamic_buffer/data.html new file mode 100644 index 0000000..382cf5e --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/data.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/is_dynamic_buffer_adapter.html b/preview/reference/boost/capy/flat_dynamic_buffer/is_dynamic_buffer_adapter.html new file mode 100644 index 0000000..43e94ab --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/is_dynamic_buffer_adapter.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::is_dynamic_buffer_adapter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/max_size.html b/preview/reference/boost/capy/flat_dynamic_buffer/max_size.html new file mode 100644 index 0000000..4e9ca1d --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/max_size.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::max_size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/mutable_buffers_type.html b/preview/reference/boost/capy/flat_dynamic_buffer/mutable_buffers_type.html new file mode 100644 index 0000000..3a5341c --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/mutable_buffers_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::mutable_buffers_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/operator_assign.html b/preview/reference/boost/capy/flat_dynamic_buffer/operator_assign.html new file mode 100644 index 0000000..fb3a4f8 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/operator_assign.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer::operator=

+
+
+
+

Copy assignment.

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+flat_dynamic_buffer&
+operator=(flat_dynamic_buffer const& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/prepare.html b/preview/reference/boost/capy/flat_dynamic_buffer/prepare.html new file mode 100644 index 0000000..c49ce86 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/prepare.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::prepare :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::flat_dynamic_buffer::prepare

+
+
+
+

Return a buffer sequence for writing.

+
+
+
+
+

Synopsis

+
+ +
+
+
mutable_buffers_type
+prepare(std::size_t n);
+
+
+
+
+
+

Description

+
+
+

Invalidates buffer sequences previously obtained from prepare.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if n > capacity().

+
+
+
+

Return Value

+
+
+

A mutable buffer sequence of size n.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

The desired number of writable bytes.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/flat_dynamic_buffer/size.html b/preview/reference/boost/capy/flat_dynamic_buffer/size.html new file mode 100644 index 0000000..2f698f4 --- /dev/null +++ b/preview/reference/boost/capy/flat_dynamic_buffer/size.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::flat_dynamic_buffer::size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/front.html b/preview/reference/boost/capy/front.html new file mode 100644 index 0000000..311d34e --- /dev/null +++ b/preview/reference/boost/capy/front.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::front :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/front_mrdocs_workaround_t.html b/preview/reference/boost/capy/front_mrdocs_workaround_t.html new file mode 100644 index 0000000..a38df0e --- /dev/null +++ b/preview/reference/boost/capy/front_mrdocs_workaround_t.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::front_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-022.html b/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-022.html new file mode 100644 index 0000000..8fd5ce3 --- /dev/null +++ b/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-022.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + boost::capy::front_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::front_mrdocs_workaround_t::operator()

+
+
+
+

Function call operator

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence ConstBufferSequence>
+requires (!MutableBufferSequence<ConstBufferSequence>)
+const_buffer
+operator()(ConstBufferSequence const& bs) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

A reference to a contiguous region of read‐only memory.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

bs

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-02a.html b/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-02a.html new file mode 100644 index 0000000..4cb8bea --- /dev/null +++ b/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-02a.html @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + boost::capy::front_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::front_mrdocs_workaround_t::operator()

+
+
+
+

Function call operators

+
+
+
+
+

Synopses

+
+ +
+

Function call operator

+
+
+
+
template<ConstBufferSequence ConstBufferSequence>
+requires (!MutableBufferSequence<ConstBufferSequence>)
+const_buffer
+operator()(ConstBufferSequence const& bs) const noexcept;
+
+
+ +
+

Function call operator

+
+
+
+
template<MutableBufferSequence MutableBufferSequence>
+mutable_buffer
+operator()(MutableBufferSequence const& bs) const noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-0c.html b/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-0c.html new file mode 100644 index 0000000..826698e --- /dev/null +++ b/preview/reference/boost/capy/front_mrdocs_workaround_t/operator_call-0c.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::front_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::front_mrdocs_workaround_t::operator()

+
+
+
+

Function call operator

+
+
+
+
+

Synopsis

+
+ +
+
+
template<MutableBufferSequence MutableBufferSequence>
+mutable_buffer
+operator()(MutableBufferSequence const& bs) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

A reference to a contiguous region of writable memory.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

bs

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/get_current_frame_allocator.html b/preview/reference/boost/capy/get_current_frame_allocator.html new file mode 100644 index 0000000..23c97c1 --- /dev/null +++ b/preview/reference/boost/capy/get_current_frame_allocator.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + boost::capy::get_current_frame_allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::get_current_frame_allocator

+
+
+
+

Return the current frame allocator for this thread.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::pmr::memory_resource*
+get_current_frame_allocator() noexcept;
+
+
+
+
+
+

Description

+
+
+

These accessors exist to implement the allocator propagation portion of the IoAwaitable protocol. Launch functions (run_async, run) set the thread‐local value before invoking a child coroutine; the child's promise_type::operator new reads it to allocate the coroutine frame from the correct resource.

+
+
+

The value is only valid during a narrow execution window. Between a coroutine's resumption and the next suspension point, the protocol guarantees that TLS contains the allocator associated with the currently running chain. Outside that window the value is indeterminate. Only code that implements an IoAwaitable should call these functions.

+
+
+

A return value of nullptr means "not specified" ‐ no allocator has been established for this chain. The awaitable is free to use whatever allocation strategy makes best sense (e.g. std::pmr::new_delete_resource()).

+
+
+

Use of the frame allocator is optional. An awaitable that does not consult this value to allocate its coroutine frame is never wrong. However, a conforming awaitable must still propagate the allocator faithfully so that downstream coroutines can use it.

+
+
+
+
+

Return Value

+
+
+

The thread‐local memory_resource pointer, or nullptr if none has been set.

+
+
+
+
+

See Also

+
+
+

set_current_frame_allocator, IoAwaitable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/get_recycling_memory_resource.html b/preview/reference/boost/capy/get_recycling_memory_resource.html new file mode 100644 index 0000000..3ed3187 --- /dev/null +++ b/preview/reference/boost/capy/get_recycling_memory_resource.html @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + boost::capy::get_recycling_memory_resource :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::get_recycling_memory_resource

+
+
+
+

Returns pointer to the default recycling memory resource.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::pmr::memory_resource*
+get_recycling_memory_resource() noexcept;
+
+
+
+
+
+

Description

+
+
+

The returned pointer is valid for the lifetime of the program. This is the default allocator used by run_async.

+
+
+
+
+

Return Value

+
+
+

Pointer to the recycling memory resource.

+
+
+
+
+

See Also

+
+
+

recycling_memory_resource

+
+
+

run_async

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/get_system_context.html b/preview/reference/boost/capy/get_system_context.html new file mode 100644 index 0000000..94946bf --- /dev/null +++ b/preview/reference/boost/capy/get_system_context.html @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + boost::capy::get_system_context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::get_system_context

+
+
+
+

Return the process‐wide system execution context.

+
+
+
+
+

Synopsis

+
+ +
+
+
thread_pool&
+get_system_context();
+
+
+
+
+
+

Description

+
+
+

This singleton context serves as a container for services but does not provide an executor or handle work.

+
+
+
+
+

Thread Safety

+
+
+

Safe to call from any thread.

+
+
+
+
+

Return Value

+
+
+

Reference to the system execution context singleton.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/immediate.html b/preview/reference/boost/capy/immediate.html new file mode 100644 index 0000000..9759a92 --- /dev/null +++ b/preview/reference/boost/capy/immediate.html @@ -0,0 +1,570 @@ + + + + + + + + + + + + + + boost::capy::immediate :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::immediate

+
+
+
+

An awaitable that completes immediately with a value.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<class T>
+struct immediate;
+
+
+
+
+
+

Description

+
+
+

This awaitable wraps a synchronous result so it can be used in contexts that require an awaitable type. It never suspends ‐ await_ready() always returns true, so the coroutine machinery is optimized away by the compiler.

+
+
+

Use this to adapt synchronous operations to satisfy async concepts like IoAwaitable without the overhead of a full coroutine frame.

+
+
+
+
+

Example

+
+
+
+
// Wrap a sync operation as an awaitable
+immediate<int> get_value()
+{
+    return {42};
+}
+
+task<void> example()
+{
+    int x = co_await get_value();  // No suspension, returns 42
+}
+
+
+
+
+
+

Satisfying WriteSink with sync operations

+
+
+
+
struct my_sync_sink
+{
+    template<ConstBufferSequence CB>
+    immediate<io_result<std::size_t>>
+    write(CB buffers)
+    {
+        auto n = process_sync(buffers);
+        return {{{}, n}};
+    }
+
+    immediate<io_result<>>
+    write_eof()
+    {
+        return {{}};
+    }
+};
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

await_ready

Always returns true ‐ this awaitable never suspends.

await_resume

await_resume overloads

await_suspend

IoAwaitable protocol overload.

+
+
+
+

Data Members

+
+ ++++ + + + + + + + + + + +

Name

Description

value_

The wrapped value.

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

ready

Create an immediate awaitable for a failed io_result.

ready

Create an immediate awaitable for a successful io_result with one value.

ready

Create an immediate awaitable for a successful io_result with three values.

ready

Create an immediate awaitable for a successful io_result with two values.

ready

Create an immediate awaitable for an io_result with error and three values.

ready

Create an immediate awaitable for an io_result with error and two values.

ready

Create an immediate awaitable for a successful io_result.

ready

Create an immediate awaitable for an io_result with error and one value.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The result type to wrap.

+
+
+
+

See Also

+
+
+

ready, io_result

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/immediate/await_ready.html b/preview/reference/boost/capy/immediate/await_ready.html new file mode 100644 index 0000000..482392e --- /dev/null +++ b/preview/reference/boost/capy/immediate/await_ready.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + boost::capy::immediate::await_ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/immediate/await_resume-00.html b/preview/reference/boost/capy/immediate/await_resume-00.html new file mode 100644 index 0000000..0e8e109 --- /dev/null +++ b/preview/reference/boost/capy/immediate/await_resume-00.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::immediate::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/immediate/await_resume-09.html b/preview/reference/boost/capy/immediate/await_resume-09.html new file mode 100644 index 0000000..0f8a866 --- /dev/null +++ b/preview/reference/boost/capy/immediate/await_resume-09.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::immediate::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::immediate::await_resume

+
+
+
+

await_resume overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+

Returns the wrapped value.

+
+
+
+
constexpr
+T
+await_resume() noexcept;
+
+
+ +
+

Returns the wrapped value (const overload).

+
+
+
+
constexpr
+T const&
+await_resume() const noexcept;
+
+
+ +
+
+
+

Return Value

+
+
+

The stored value, moved if non‐const.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/immediate/await_resume-0e.html b/preview/reference/boost/capy/immediate/await_resume-0e.html new file mode 100644 index 0000000..1121821 --- /dev/null +++ b/preview/reference/boost/capy/immediate/await_resume-0e.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::immediate::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/immediate/await_suspend.html b/preview/reference/boost/capy/immediate/await_suspend.html new file mode 100644 index 0000000..2b3c842 --- /dev/null +++ b/preview/reference/boost/capy/immediate/await_suspend.html @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + boost::capy::immediate::await_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::immediate::await_suspend

+
+
+
+

IoAwaitable protocol overload.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
std::coroutine_handle
+await_suspend(
+    std::coroutine_handle h,
+    io_env const* env) const noexcept;
+
+
+
+
+
+

Description

+
+
+

This overload allows immediate to satisfy the IoAwaitable concept. Since the result is already available, the environment is unused.

+
+
+
+
+

Return Value

+
+
+

std::noop_coroutine() to indicate no suspension.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

h

The coroutine handle (unused).

env

The execution environment (unused).

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/immediate/value_.html b/preview/reference/boost/capy/immediate/value_.html new file mode 100644 index 0000000..b577c84 --- /dev/null +++ b/preview/reference/boost/capy/immediate/value_.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::immediate::value_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base.html b/preview/reference/boost/capy/io_awaitable_promise_base.html new file mode 100644 index 0000000..88b7bb1 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base.html @@ -0,0 +1,625 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base

+
+
+
+

CRTP mixin that adds I/O awaitable support to a promise type.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename Derived>
+class io_awaitable_promise_base;
+
+
+
+
+
+

Description

+
+
+

Inherit from this class to enable these capabilities in your coroutine:

+
+
+

1. Frame allocation — The mixin provides operator new/delete that use the thread‐local frame allocator set by run_async.

+
+
+

2. Environment storage — The mixin stores a pointer to the io_env containing the executor, stop token, and allocator for this coroutine.

+
+
+

3. Environment access — Coroutine code can retrieve the environment via co_await this_coro::environment, or individual fields via co_await this_coro::executor, co_await this_coro::stop_token, and co_await this_coro::allocator.

+
+
+
+
+

Basic Usage

+
+
+

For coroutines that need to access their execution environment:

+
+
+
+
struct my_task
+{
+    struct promise_type : io_awaitable_promise_base<promise_type>
+    {
+        my_task get_return_object();
+        std::suspend_always initial_suspend() noexcept;
+        std::suspend_always final_suspend() noexcept;
+        void return_void();
+        void unhandled_exception();
+    };
+
+    // ... awaitable interface ...
+};
+
+my_task example()
+{
+    auto env = co_await this_coro::environment;
+    // Access env->executor, env->stop_token, env->allocator
+
+    // Or use fine-grained accessors:
+    auto ex = co_await this_coro::executor;
+    auto token = co_await this_coro::stop_token;
+    auto* alloc = co_await this_coro::allocator;
+}
+
+
+
+
+
+

Custom Awaitable Transformation

+
+
+

If your promise needs to transform awaitables (e.g., for affinity or logging), override transform_awaitable instead of await_transform:

+
+
+
+
struct promise_type : io_awaitable_promise_base<promise_type>
+{
+    template<typename A>
+    auto transform_awaitable(A&& a)
+    {
+        // Your custom transformation logic
+        return std::forward<A>(a);
+    }
+};
+
+
+
+

The mixin's await_transform intercepts this_coro::environment_tag and the fine‐grained tag types (this_coro::executor_tag, this_coro::stop_token_tag, this_coro::allocator_tag), then delegates all other awaitables to your transform_awaitable.

+
+
+
+
+

Making Your Coroutine an IoAwaitable

+
+
+

The mixin handles the "inside the coroutine" part—accessing the environment. To receive the environment when your coroutine is awaited (satisfying IoAwaitable), implement the await_suspend overload on your coroutine return type:

+
+
+
+
struct my_task
+{
+    struct promise_type : io_awaitable_promise_base<promise_type> { ... };
+
+    std::coroutine_handle<promise_type> h_;
+
+    // IoAwaitable await_suspend receives and stores the environment
+    std::coroutine_handle<> await_suspend(std::coroutine_handle<> cont, io_env const* env)
+    {
+        h_.promise().set_environment(env);
+        // ... rest of suspend logic ...
+    }
+};
+
+
+
+
+
+

Thread Safety

+
+
+

The environment is stored during await_suspend and read during co_await this_coro::environment. These occur on the same logical thread of execution, so no synchronization is required.

+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

~io_awaitable_promise_base [destructor]

Destructor

await_transform

Intercept co_await expressions.

continuation

Return and consume the stored continuation handle.

environment

Return the stored execution environment.

set_continuation

Store the continuation to resume on completion.

set_environment

Store a pointer to the execution environment.

transform_awaitable

Transform an awaitable before co_await.

+
+
+
+

Static Member Functions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

operator delete

Deallocate a coroutine frame.

operator new

Allocate a coroutine frame.

+
+
+
+

Derived Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

promise_type

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Derived

The derived promise type (CRTP pattern).

+
+
+
+

See Also

+
+
+

this_coro::environment, this_coro::executor, this_coro::stop_token, this_coro::allocator

+
+
+

io_env

+
+
+

IoAwaitable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/2destructor.html b/preview/reference/boost/capy/io_awaitable_promise_base/2destructor.html new file mode 100644 index 0000000..63acae7 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::~io_awaitable_promise_base :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/await_transform.html b/preview/reference/boost/capy/io_awaitable_promise_base/await_transform.html new file mode 100644 index 0000000..38c1fdb --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/await_transform.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::await_transform :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::await_transform

+
+
+
+

Intercept co_await expressions.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename T>
+auto
+await_transform(T&& t);
+
+
+
+
+
+

Description

+
+
+

This function handles this_coro::environment_tag and the fine‐grained tags (this_coro::executor_tag, this_coro::stop_token_tag, this_coro::allocator_tag) specially, returning an awaiter that yields the stored value. All other awaitables are delegated to transform_awaitable.

+
+
+
+
+

Return Value

+
+
+

An awaiter for the expression.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

t

The awaited expression.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/continuation.html b/preview/reference/boost/capy/io_awaitable_promise_base/continuation.html new file mode 100644 index 0000000..512ecf7 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/continuation.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::continuation :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::continuation

+
+
+
+

Return and consume the stored continuation handle.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+continuation() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Resets the stored handle to noop_coroutine() so the destructor will not double‐destroy it.

+
+
+
+
+

Return Value

+
+
+

The continuation for symmetric transfer.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/environment.html b/preview/reference/boost/capy/io_awaitable_promise_base/environment.html new file mode 100644 index 0000000..689c071 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/environment.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::environment :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/operator_del.html b/preview/reference/boost/capy/io_awaitable_promise_base/operator_del.html new file mode 100644 index 0000000..027bb9f --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/operator_del.html @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::operator delete :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::operator delete

+
+
+
+

Deallocate a coroutine frame.

+
+
+
+
+

Synopsis

+
+ +
+
+
static
+void
+operator delete(
+    void* ptr,
+    std::size_t size) noexcept;
+
+
+
+
+
+

Description

+
+
+

Reads the allocator pointer stored at the end of the frame to ensure correct deallocation regardless of current TLS. Bypasses virtual dispatch for the recycling allocator.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/operator_new.html b/preview/reference/boost/capy/io_awaitable_promise_base/operator_new.html new file mode 100644 index 0000000..15ced54 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/operator_new.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::operator new :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::operator new

+
+
+
+

Allocate a coroutine frame.

+
+
+
+
+

Synopsis

+
+ +
+
+
static
+void*
+operator new(std::size_t size);
+
+
+
+
+
+

Description

+
+
+

Uses the thread‐local frame allocator set by run_async. Falls back to default memory resource if not set. Stores the allocator pointer at the end of each frame for correct deallocation even when TLS changes. Uses memcpy to avoid alignment requirements on the trailing pointer. Bypasses virtual dispatch for the recycling allocator.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/set_continuation.html b/preview/reference/boost/capy/io_awaitable_promise_base/set_continuation.html new file mode 100644 index 0000000..8772e65 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/set_continuation.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::set_continuation :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::set_continuation

+
+
+
+

Store the continuation to resume on completion.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+set_continuation(std::coroutine_handle cont) noexcept;
+
+
+
+
+
+

Description

+
+
+

Call this from your coroutine type's await_suspend overload to set up the completion path. The final_suspend awaiter returns this handle via unconditional symmetric transfer.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

cont

The continuation to resume on completion.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/set_environment.html b/preview/reference/boost/capy/io_awaitable_promise_base/set_environment.html new file mode 100644 index 0000000..2c0068f --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/set_environment.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::set_environment :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::set_environment

+
+
+
+

Store a pointer to the execution environment.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+set_environment(io_env const* env) noexcept;
+
+
+
+
+
+

Description

+
+
+

Call this from your coroutine type's await_suspend overload to make the environment available via co_await this_coro::environment. The pointed‐to io_env must outlive this coroutine.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

env

The environment to store.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_awaitable_promise_base/transform_awaitable.html b/preview/reference/boost/capy/io_awaitable_promise_base/transform_awaitable.html new file mode 100644 index 0000000..d9351b1 --- /dev/null +++ b/preview/reference/boost/capy/io_awaitable_promise_base/transform_awaitable.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::io_awaitable_promise_base::transform_awaitable :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_awaitable_promise_base::transform_awaitable

+
+
+
+

Transform an awaitable before co_await.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<typename A>
+decltype(auto)
+transform_awaitable(A&& a);
+
+
+
+
+
+

Description

+
+
+

Override this in your derived promise type to customize how awaitables are transformed. The default implementation passes the awaitable through unchanged.

+
+
+
+
+

Return Value

+
+
+

The transformed awaitable.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

a

The awaitable expression from co_await a.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_env.html b/preview/reference/boost/capy/io_env.html new file mode 100644 index 0000000..b2b8c9f --- /dev/null +++ b/preview/reference/boost/capy/io_env.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + boost::capy::io_env :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_env

+
+
+
+

Execution environment for IoAwaitables.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/io_env.hpp>

+
+
+
+
struct io_env;
+
+
+
+
+
+

Description

+
+
+

This struct bundles the execution context passed through coroutine chains via the IoAwaitable protocol. It contains the executor for resumption, a stop token for cancellation, and an optional allocator for coroutine frame allocation.

+
+
+
+
+

Lifetime

+
+
+

Launch functions (run_async, run) own the io_env and guarantee it outlives all tasks and awaitables in the launched chain. Awaitables receive io_env const* in await_suspend and should store it directly, never copy the pointed‐to object.

+
+
+
+
+

Thread Safety

+
+
+

The referenced executor and allocator must remain valid for the lifetime of any coroutine using this environment.

+
+
+
+
+

Data Members

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

allocator

The allocator for coroutine frame allocation.

executor

The executor for coroutine resumption.

stop_token

The stop token for cancellation propagation.

+
+
+
+

See Also

+
+
+

IoAwaitable, IoRunnable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_env/allocator.html b/preview/reference/boost/capy/io_env/allocator.html new file mode 100644 index 0000000..a4a299d --- /dev/null +++ b/preview/reference/boost/capy/io_env/allocator.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::io_env::allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_env/executor.html b/preview/reference/boost/capy/io_env/executor.html new file mode 100644 index 0000000..a520c4f --- /dev/null +++ b/preview/reference/boost/capy/io_env/executor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::io_env::executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_env/stop_token.html b/preview/reference/boost/capy/io_env/stop_token.html new file mode 100644 index 0000000..f9d8ed0 --- /dev/null +++ b/preview/reference/boost/capy/io_env/stop_token.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::io_env::stop_token :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-02.html b/preview/reference/boost/capy/io_result-02.html new file mode 100644 index 0000000..7f9fe36 --- /dev/null +++ b/preview/reference/boost/capy/io_result-02.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2, T3> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-02/ec.html b/preview/reference/boost/capy/io_result-02/ec.html new file mode 100644 index 0000000..62b9331 --- /dev/null +++ b/preview/reference/boost/capy/io_result-02/ec.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2, T3>::ec :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-02/t1.html b/preview/reference/boost/capy/io_result-02/t1.html new file mode 100644 index 0000000..73a15e9 --- /dev/null +++ b/preview/reference/boost/capy/io_result-02/t1.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2, T3>::t1 :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-02/t2.html b/preview/reference/boost/capy/io_result-02/t2.html new file mode 100644 index 0000000..ca7f8c9 --- /dev/null +++ b/preview/reference/boost/capy/io_result-02/t2.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2, T3>::t2 :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-02/t3.html b/preview/reference/boost/capy/io_result-02/t3.html new file mode 100644 index 0000000..c697db3 --- /dev/null +++ b/preview/reference/boost/capy/io_result-02/t3.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2, T3>::t3 :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-07.html b/preview/reference/boost/capy/io_result-07.html new file mode 100644 index 0000000..ba76bb3 --- /dev/null +++ b/preview/reference/boost/capy/io_result-07.html @@ -0,0 +1,468 @@ + + + + + + + + + + + + + + boost::capy::io_result :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_result

+
+
+
+

Result type for asynchronous I/O operations.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io_result.hpp>

+
+
+
+
template<class... Args>
+struct io_result;
+
+
+
+
+
+

Description

+
+
+

This template provides a unified result type for async operations, always containing a std::error_code plus optional additional values. It supports structured bindings.

+
+
+
+
+

Usage

+
+
+
+
auto [ec, n] = co_await s.read_some(buf);
+if (ec) { ... }
+
+
+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

ready

Create an immediate awaitable for a successful io_result with one value.

ready

Create an immediate awaitable for a successful io_result with three values.

ready

Create an immediate awaitable for a successful io_result with two values.

ready

Create an immediate awaitable for an io_result with error and three values.

ready

Create an immediate awaitable for an io_result with error and two values.

ready

Create an immediate awaitable for an io_result with error and one value.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Args

Additional value types beyond the error code.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0c.html b/preview/reference/boost/capy/io_result-0c.html new file mode 100644 index 0000000..f08f2b3 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0c.html @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + boost::capy::io_result<> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_result<>

+
+
+
+

Result type for void operations.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io_result.hpp>

+
+
+
+
template<>
+struct io_result<>;
+
+
+
+
+
+

Description

+
+
+

Used by operations like connect() that don't return a value beyond success/failure. This specialization is not an aggregate to enable implicit conversion from error_code.

+
+
+
+
+

Example

+
+
+
+
auto [ec] = co_await s.connect(ep);
+if (ec) { ... }
+
+
+
+
+
+

Data Members

+
+ ++++ + + + + + + + + + + +

Name

Description

ec

The error code from the operation.

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

ready

Create an immediate awaitable for a failed io_result.

ready

Create an immediate awaitable for a successful io_result.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0c/ec.html b/preview/reference/boost/capy/io_result-0c/ec.html new file mode 100644 index 0000000..5c3d366 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0c/ec.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::io_result<>::ec :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e1.html b/preview/reference/boost/capy/io_result-0e1.html new file mode 100644 index 0000000..a7f0759 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e1.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_result<T1>

+
+
+
+

Result type for byte transfer operations.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io_result.hpp>

+
+
+
+
template<typename T1>
+struct io_result<T1>;
+
+
+
+
+
+

Description

+
+
+

Used by operations like read_some() and write_some() that return the number of bytes transferred.

+
+
+
+
+

Example

+
+
+
+
auto [ec, n] = co_await s.read_some(buf);
+if (ec) { ... }
+
+
+
+
+
+

Data Members

+
+ +++ + + + + + + + + + + + +

Name

ec

t1

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e1/ec.html b/preview/reference/boost/capy/io_result-0e1/ec.html new file mode 100644 index 0000000..814112c --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e1/ec.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1>::ec :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e1/t1.html b/preview/reference/boost/capy/io_result-0e1/t1.html new file mode 100644 index 0000000..80f0326 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e1/t1.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1>::t1 :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e7.html b/preview/reference/boost/capy/io_result-0e7.html new file mode 100644 index 0000000..b55e221 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e7.html @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e7/ec.html b/preview/reference/boost/capy/io_result-0e7/ec.html new file mode 100644 index 0000000..11ceafa --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e7/ec.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2>::ec :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e7/t1.html b/preview/reference/boost/capy/io_result-0e7/t1.html new file mode 100644 index 0000000..a1460d2 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e7/t1.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2>::t1 :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_result-0e7/t2.html b/preview/reference/boost/capy/io_result-0e7/t2.html new file mode 100644 index 0000000..f5ce729 --- /dev/null +++ b/preview/reference/boost/capy/io_result-0e7/t2.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::io_result<T1, T2>::t2 :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/io_task.html b/preview/reference/boost/capy/io_task.html new file mode 100644 index 0000000..985669f --- /dev/null +++ b/preview/reference/boost/capy/io_task.html @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + boost::capy::io_task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::io_task

+
+
+
+

A task type for I/O operations yielding io_result.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io_task.hpp>

+
+
+
+
template<class... Ts>
+using io_task = task<io_result<Ts...>>;
+
+
+
+
+
+

Description

+
+
+

This is a convenience alias for task<io_result<Ts...>>. The converting constructor on io_result<> allows direct co_return of error codes:

+
+
+
+
io_task<> connect_to_server(socket& s, endpoint ep)
+{
+    co_return co_await s.connect(ep);  // returns io_result<>
+}
+
+io_task<> handler(route_params& rp)
+{
+    co_return route::next;  // error_code converts to io_result<>
+}
+
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Ts

Additional value types beyond error_code.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/keep_prefix.html b/preview/reference/boost/capy/keep_prefix.html new file mode 100644 index 0000000..15d79cf --- /dev/null +++ b/preview/reference/boost/capy/keep_prefix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::keep_prefix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/keep_prefix_mrdocs_workaround_t.html b/preview/reference/boost/capy/keep_prefix_mrdocs_workaround_t.html new file mode 100644 index 0000000..cc122b9 --- /dev/null +++ b/preview/reference/boost/capy/keep_prefix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::keep_prefix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/keep_prefix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/keep_prefix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..c4e2d9c --- /dev/null +++ b/preview/reference/boost/capy/keep_prefix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::keep_prefix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/keep_suffix.html b/preview/reference/boost/capy/keep_suffix.html new file mode 100644 index 0000000..db337e9 --- /dev/null +++ b/preview/reference/boost/capy/keep_suffix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::keep_suffix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/keep_suffix_mrdocs_workaround_t.html b/preview/reference/boost/capy/keep_suffix_mrdocs_workaround_t.html new file mode 100644 index 0000000..dc9ecca --- /dev/null +++ b/preview/reference/boost/capy/keep_suffix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::keep_suffix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/keep_suffix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/keep_suffix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..dd2d52c --- /dev/null +++ b/preview/reference/boost/capy/keep_suffix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::keep_suffix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-002.html b/preview/reference/boost/capy/make_buffer-002.html new file mode 100644 index 0000000..edc2633 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-002.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::array with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::array<T, N> const& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::array with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-00a.html b/preview/reference/boost/capy/make_buffer-00a.html new file mode 100644 index 0000000..37591eb --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-00a.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-00b4.html b/preview/reference/boost/capy/make_buffer-00b4.html new file mode 100644 index 0000000..967a3c0 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-00b4.html @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-00bc.html b/preview/reference/boost/capy/make_buffer-00bc.html new file mode 100644 index 0000000..29f5256 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-00bc.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::span with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (sizeof(T) == 1)
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::span<T const, Extent> data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::span with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-010.html b/preview/reference/boost/capy/make_buffer-010.html new file mode 100644 index 0000000..287145a --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-010.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::vector with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::vector<T, Allocator>& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::vector with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-011.html b/preview/reference/boost/capy/make_buffer-011.html new file mode 100644 index 0000000..88e0bbb --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-011.html @@ -0,0 +1,951 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

make_buffer overloads

+
+
+
+
+

Synopses

+
+ +
+

Return a buffer.

+
+
+
+
[[nodiscard]]
+const_buffer
+make_buffer(const_buffer const& b) noexcept;
+
+
+ +
+

Return a buffer.

+
+
+
+
[[nodiscard]]
+mutable_buffer
+make_buffer(mutable_buffer const& b) noexcept;
+
+
+ +
+

Return a buffer from a mutable contiguous range.

+
+
+
+
template</* implementation-defined */ T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(T& data) noexcept;
+
+
+ +
+

Return a buffer from a const contiguous range.

+
+
+
+
template</* implementation-defined */ T>
+[[nodiscard]]
+const_buffer
+make_buffer(T const& data) noexcept;
+
+
+ +
+

Return a buffer from a std::basic_string_view.

+
+
+
+
template<
+    class CharT,
+    class Traits>
+[[nodiscard]]
+const_buffer
+make_buffer(std::basic_string_view<CharT, Traits> data) noexcept;
+
+
+ +
+

Return a buffer from a mutable std::span.

+
+
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (!std::is_const_v<T> && sizeof(T) == 1)
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::span<T, Extent> data) noexcept;
+
+
+ +
+

Return a buffer from a const std::span.

+
+
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (sizeof(T) == 1)
+[[nodiscard]]
+const_buffer
+make_buffer(std::span<T const, Extent> data) noexcept;
+
+
+ +
+

Return a buffer from a std::array.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::array<T, N>& data) noexcept;
+
+
+ +
+

Return a buffer from a std::vector.

+
+
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::vector<T, Allocator>& data) noexcept;
+
+
+ +
+

Return a buffer from a const std::array.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(std::array<T, N> const& data) noexcept;
+
+
+ +
+

Return a buffer from a const std::vector.

+
+
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(std::vector<T, Allocator> const& data) noexcept;
+
+
+ +
+

Return a buffer from a C‐style array.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(T(& data)[]) noexcept;
+
+
+ +
+

Return a buffer from a const C‐style array.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(T const(& data)[]) noexcept;
+
+
+ +
+

Return a buffer from a std::basic_string.

+
+
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::basic_string<CharT, Traits, Allocator>& data) noexcept;
+
+
+ +
+

Return a buffer from a const std::basic_string.

+
+
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+const_buffer
+make_buffer(std::basic_string<CharT, Traits, Allocator> const& data) noexcept;
+
+
+ +
+

Return a buffer with a maximum size.

+
+
+
+
[[nodiscard]]
+const_buffer
+make_buffer(
+    const_buffer const& b,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer with a maximum size.

+
+
+
+
[[nodiscard]]
+mutable_buffer
+make_buffer(
+    mutable_buffer const& b,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer.

+
+
+
+
[[nodiscard]]
+mutable_buffer
+make_buffer(
+    void* data,
+    std::size_t size) noexcept;
+
+
+ +
+

Return a buffer.

+
+
+
+
[[nodiscard]]
+const_buffer
+make_buffer(
+    void const* data,
+    std::size_t size) noexcept;
+
+
+ +
+

Return a buffer from a mutable contiguous range with a maximum size.

+
+
+
+
template</* implementation-defined */ T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    T& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a const contiguous range with a maximum size.

+
+
+
+
template</* implementation-defined */ T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    T const& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a std::basic_string_view with a maximum size.

+
+
+
+
template<
+    class CharT,
+    class Traits>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::basic_string_view<CharT, Traits> data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a mutable std::span with a maximum size.

+
+
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (!std::is_const_v<T> && sizeof(T) == 1)
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::span<T, Extent> data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a const std::span with a maximum size.

+
+
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (sizeof(T) == 1)
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::span<T const, Extent> data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a std::array with a maximum size.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::array<T, N>& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a std::vector with a maximum size.

+
+
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::vector<T, Allocator>& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a const std::array with a maximum size.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::array<T, N> const& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a const std::vector with a maximum size.

+
+
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::vector<T, Allocator> const& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a C‐style array with a maximum size.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    T(& data)[],
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a const C‐style array with a maximum size.

+
+
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    T const(& data)[],
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a std::basic_string with a maximum size.

+
+
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::basic_string<CharT, Traits, Allocator>& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer from a const std::basic_string with a maximum size.

+
+
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::basic_string<CharT, Traits, Allocator> const& data,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer with a maximum size.

+
+
+
+
[[nodiscard]]
+mutable_buffer
+make_buffer(
+    void* data,
+    std::size_t size,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Return a buffer with a maximum size.

+
+
+
+
[[nodiscard]]
+const_buffer
+make_buffer(
+    void const* data,
+    std::size_t size,
+    std::size_t max_size) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0138.html b/preview/reference/boost/capy/make_buffer-0138.html new file mode 100644 index 0000000..8c5bb3b --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0138.html @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
[[nodiscard]]
+const_buffer
+make_buffer(
+    const_buffer const& b,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer with a maximum size.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

b

A reference to a contiguous region of read‐only memory.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0139.html b/preview/reference/boost/capy/make_buffer-0139.html new file mode 100644 index 0000000..7b3bf58 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0139.html @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
[[nodiscard]]
+mutable_buffer
+make_buffer(
+    mutable_buffer const& b,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer with a maximum size.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

b

A reference to a contiguous region of writable memory.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-02.html b/preview/reference/boost/capy/make_buffer-02.html new file mode 100644 index 0000000..e272b87 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-02.html @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::basic_string_view.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits>
+[[nodiscard]]
+const_buffer
+make_buffer(std::basic_string_view<CharT, Traits> data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::basic_string_view.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-030.html b/preview/reference/boost/capy/make_buffer-030.html new file mode 100644 index 0000000..27b58c6 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-030.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::vector.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(std::vector<T, Allocator> const& data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::vector.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-037.html b/preview/reference/boost/capy/make_buffer-037.html new file mode 100644 index 0000000..b0b67c5 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-037.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::basic_string with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::basic_string<CharT, Traits, Allocator>& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::basic_string with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-039.html b/preview/reference/boost/capy/make_buffer-039.html new file mode 100644 index 0000000..c2dd179 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-039.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const C‐style array.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(T const(& data)[]) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const C‐style array.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-03c.html b/preview/reference/boost/capy/make_buffer-03c.html new file mode 100644 index 0000000..3ff07e6 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-03c.html @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::basic_string_view with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::basic_string_view<CharT, Traits> data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::basic_string_view with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-03d.html b/preview/reference/boost/capy/make_buffer-03d.html new file mode 100644 index 0000000..77c70f8 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-03d.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a C‐style array with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    T(& data)[],
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a C‐style array with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-041.html b/preview/reference/boost/capy/make_buffer-041.html new file mode 100644 index 0000000..efa4674 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-041.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-042.html b/preview/reference/boost/capy/make_buffer-042.html new file mode 100644 index 0000000..c42b11d --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-042.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::array.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(std::array<T, N> const& data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::array.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-043.html b/preview/reference/boost/capy/make_buffer-043.html new file mode 100644 index 0000000..f2d4d80 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-043.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a mutable std::span with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (!std::is_const_v<T> && sizeof(T) == 1)
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::span<T, Extent> data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a mutable std::span with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-045.html b/preview/reference/boost/capy/make_buffer-045.html new file mode 100644 index 0000000..5314974 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-045.html @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-048.html b/preview/reference/boost/capy/make_buffer-048.html new file mode 100644 index 0000000..bcea49c --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-048.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::basic_string.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+const_buffer
+make_buffer(std::basic_string<CharT, Traits, Allocator> const& data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::basic_string.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-060.html b/preview/reference/boost/capy/make_buffer-060.html new file mode 100644 index 0000000..49545d2 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-060.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0612.html b/preview/reference/boost/capy/make_buffer-0612.html new file mode 100644 index 0000000..df3a7a6 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0612.html @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-061e.html b/preview/reference/boost/capy/make_buffer-061e.html new file mode 100644 index 0000000..ba749ac --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-061e.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::basic_string.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::basic_string<CharT, Traits, Allocator>& data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::basic_string.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-06a.html b/preview/reference/boost/capy/make_buffer-06a.html new file mode 100644 index 0000000..3f724d3 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-06a.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::span.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (sizeof(T) == 1)
+[[nodiscard]]
+const_buffer
+make_buffer(std::span<T const, Extent> data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::span.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-06b.html b/preview/reference/boost/capy/make_buffer-06b.html new file mode 100644 index 0000000..908ae5a --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-06b.html @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-06e.html b/preview/reference/boost/capy/make_buffer-06e.html new file mode 100644 index 0000000..955e2a3 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-06e.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a mutable std::span.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t Extent>
+requires (!std::is_const_v<T> && sizeof(T) == 1)
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::span<T, Extent> data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a mutable std::span.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-081.html b/preview/reference/boost/capy/make_buffer-081.html new file mode 100644 index 0000000..4991768 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-081.html @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const contiguous range with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template</* implementation-defined */ T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    T const& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const contiguous range with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-085.html b/preview/reference/boost/capy/make_buffer-085.html new file mode 100644 index 0000000..8875c05 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-085.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::vector.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(std::vector<T, Allocator>& data) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::vector.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-08f.html b/preview/reference/boost/capy/make_buffer-08f.html new file mode 100644 index 0000000..13b7598 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-08f.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-09e.html b/preview/reference/boost/capy/make_buffer-09e.html new file mode 100644 index 0000000..dd7603f --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-09e.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const C‐style array with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    T const(& data)[],
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const C‐style array with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-09f.html b/preview/reference/boost/capy/make_buffer-09f.html new file mode 100644 index 0000000..4c44422 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-09f.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::vector with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    class Allocator>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::vector<T, Allocator> const& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::vector with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0a.html b/preview/reference/boost/capy/make_buffer-0a.html new file mode 100644 index 0000000..4c995fa --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0a.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a std::array with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class T,
+    std::size_t N>
+requires std::is_trivially_copyable_v<T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    std::array<T, N>& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a std::array with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0b.html b/preview/reference/boost/capy/make_buffer-0b.html new file mode 100644 index 0000000..1c4842e --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0b.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a const std::basic_string with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<
+    class CharT,
+    class Traits,
+    class Allocator>
+[[nodiscard]]
+const_buffer
+make_buffer(
+    std::basic_string<CharT, Traits, Allocator> const& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a const std::basic_string with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0e.html b/preview/reference/boost/capy/make_buffer-0e.html new file mode 100644 index 0000000..f266616 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0e.html @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0f1.html b/preview/reference/boost/capy/make_buffer-0f1.html new file mode 100644 index 0000000..9c1bb44 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0f1.html @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_buffer-0f6.html b/preview/reference/boost/capy/make_buffer-0f6.html new file mode 100644 index 0000000..cd94769 --- /dev/null +++ b/preview/reference/boost/capy/make_buffer-0f6.html @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + boost::capy::make_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_buffer

+
+
+
+

Return a buffer from a mutable contiguous range with a maximum size.

+
+
+
+
+

Synopsis

+
+ +
+
+
template</* implementation-defined */ T>
+[[nodiscard]]
+mutable_buffer
+make_buffer(
+    T& data,
+    std::size_t max_size) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

a buffer from a mutable contiguous range with a maximum size.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/make_error_code.html b/preview/reference/boost/capy/make_error_code.html new file mode 100644 index 0000000..0b48c7a --- /dev/null +++ b/preview/reference/boost/capy/make_error_code.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::make_error_code :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_error_condition.html b/preview/reference/boost/capy/make_error_condition.html new file mode 100644 index 0000000..add046c --- /dev/null +++ b/preview/reference/boost/capy/make_error_condition.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::make_error_condition :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/make_work_guard.html b/preview/reference/boost/capy/make_work_guard.html new file mode 100644 index 0000000..e34a7e4 --- /dev/null +++ b/preview/reference/boost/capy/make_work_guard.html @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + boost::capy::make_work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::make_work_guard

+
+
+
+

Create a work guard from an executor.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<Executor Ex>
+work_guard<Ex>
+make_work_guard(Ex ex);
+
+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Return Value

+
+
+

A work_guard holding work on ex.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The executor to create the guard for.

+
+
+
+

See Also

+
+
+

work_guard

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/match_delim.html b/preview/reference/boost/capy/match_delim.html new file mode 100644 index 0000000..820afcc --- /dev/null +++ b/preview/reference/boost/capy/match_delim.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::match_delim :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::match_delim

+
+
+
+

Match condition that searches for a delimiter string.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/read_until.hpp>

+
+
+
+
struct match_delim;
+
+
+
+
+
+

Description

+
+
+

Satisfies MatchCondition. Returns the position after the delimiter when found, or npos otherwise. Provides an overlap hint of delim.size() ‐ 1 to handle delimiters spanning reads.

+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+
+
+

Data Members

+
+ +++ + + + + + + + + +

Name

delim

+
+
+
+

See Also

+
+
+

MatchCondition, read_until

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/match_delim/delim.html b/preview/reference/boost/capy/match_delim/delim.html new file mode 100644 index 0000000..e13c565 --- /dev/null +++ b/preview/reference/boost/capy/match_delim/delim.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::match_delim::delim :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/match_delim/operator_call.html b/preview/reference/boost/capy/match_delim/operator_call.html new file mode 100644 index 0000000..5994298 --- /dev/null +++ b/preview/reference/boost/capy/match_delim/operator_call.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + boost::capy::match_delim::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer.html b/preview/reference/boost/capy/mutable_buffer.html new file mode 100644 index 0000000..6f69d9b --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer.html @@ -0,0 +1,565 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer

+
+
+
+

A reference to a contiguous region of writable memory.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
class mutable_buffer
+    : public /* implementation-defined */
+
+
+
+
+
+

Description

+
+
+

Represents a pointer and size pair for a modifiable byte range. Does not own the memory. Satisfies MutableBufferSequence (as a single‐element sequence) and is implicitly convertible to const_buffer.

+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

/* implementation-defined */

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

mutable_buffer [constructor]

Constructors

operator=

Copy assignment.

data

Return a pointer to the memory region.

operator+=

Advance the buffer start, shrinking the region.

size

Return the size in bytes.

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::tag_invoke

Slice customization point for tag_invoke.

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

make_buffer

Return a buffer.

make_buffer

Return a buffer from a std::vector with a maximum size.

make_buffer

Return a buffer with a maximum size.

make_buffer

Return a buffer from a std::basic_string with a maximum size.

make_buffer

Return a buffer from a C‐style array with a maximum size.

make_buffer

Return a buffer from a std::array.

make_buffer

Return a buffer from a mutable std::span with a maximum size.

make_buffer

Return a buffer from a C‐style array.

make_buffer

Return a buffer from a std::basic_string.

make_buffer

Return a buffer with a maximum size.

make_buffer

Return a buffer from a mutable std::span.

make_buffer

Return a buffer from a std::vector.

make_buffer

Return a buffer from a std::array with a maximum size.

make_buffer

Return a buffer from a mutable contiguous range.

make_buffer

Return a buffer.

make_buffer

Return a buffer from a mutable contiguous range with a maximum size.

+
+
+
+

See Also

+
+
+

const_buffer, MutableBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/2constructor-00.html b/preview/reference/boost/capy/mutable_buffer/2constructor-00.html new file mode 100644 index 0000000..038e9bd --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/2constructor-00.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/2constructor-03.html b/preview/reference/boost/capy/mutable_buffer/2constructor-03.html new file mode 100644 index 0000000..903b2b2 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/2constructor-03.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer::mutable_buffer

+
+
+
+

Construct from Asio mutable_buffer.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
template<class MutableBuffer>
+requires std::same_as<MutableBuffer, asio::mutable_buffer>
+constexpr
+mutable_buffer(MutableBuffer const& b) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

b

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/2constructor-09.html b/preview/reference/boost/capy/mutable_buffer/2constructor-09.html new file mode 100644 index 0000000..3632e3d --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/2constructor-09.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/2constructor-0a.html b/preview/reference/boost/capy/mutable_buffer/2constructor-0a.html new file mode 100644 index 0000000..a989e14 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/2constructor-0a.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/2constructor-0b.html b/preview/reference/boost/capy/mutable_buffer/2constructor-0b.html new file mode 100644 index 0000000..09668c5 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/2constructor-0b.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer::mutable_buffer

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+

Construct an empty buffer.

+
+
+
+
constexpr
+mutable_buffer() = default;
+
+
+ +
+

Copy constructor.

+
+
+
+
constexpr
+mutable_buffer(mutable_buffer const& other) = default;
+
+
+ +
+

Construct from Asio mutable_buffer.

+
+
+
+
template<class MutableBuffer>
+requires std::same_as<MutableBuffer, asio::mutable_buffer>
+constexpr
+mutable_buffer(MutableBuffer const& b) noexcept;
+
+
+ +
+

Construct from pointer and size.

+
+
+
+
constexpr
+mutable_buffer(
+    void* data,
+    std::size_t size) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/data.html b/preview/reference/boost/capy/mutable_buffer/data.html new file mode 100644 index 0000000..e15a8fa --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/data.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::data :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/operator_assign.html b/preview/reference/boost/capy/mutable_buffer/operator_assign.html new file mode 100644 index 0000000..2aa069a --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/operator_assign.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/operator_plus_eq.html b/preview/reference/boost/capy/mutable_buffer/operator_plus_eq.html new file mode 100644 index 0000000..a4e0eba --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/operator_plus_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::operator+= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer::operator+=

+
+
+
+

Advance the buffer start, shrinking the region.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
mutable_buffer&
+operator+=(std::size_t n) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

n

Bytes to skip. Clamped to size().

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer/size.html b/preview/reference/boost/capy/mutable_buffer/size.html new file mode 100644 index 0000000..ad951a1 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer/size.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer::size :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype.html b/preview/reference/boost/capy/mutable_buffer_archetype.html new file mode 100644 index 0000000..c44e56f --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_.html b/preview/reference/boost/capy/mutable_buffer_archetype_.html new file mode 100644 index 0000000..d7cb2fb --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_.html @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_

+
+
+
+

Archetype for MutableBufferSequence concept checking.

+
+
+
+
+

Synopsis

+
+ +
+
+
struct mutable_buffer_archetype_;
+
+
+
+
+
+

Description

+
+
+

This type satisfies MutableBufferSequence but cannot be instantiated. Use it in concept definitions to verify that a function template accepts any MutableBufferSequence.

+
+
+
+
+

Example

+
+
+
+
template<typename T>
+concept MyReadable =
+    requires(T& stream, mutable_buffer_archetype buffers)
+    {
+        stream.read(buffers);
+    };
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

mutable_buffer_archetype_ [constructor] [deleted]

Constructors

operator=

Assignment operators

operator const_buffer

Conversion to const_buffer

operator mutable_buffer

Conversion to mutable_buffer

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-06.html b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-06.html new file mode 100644 index 0000000..2ecc733 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-06.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_

+
+
+
+

Copy constructor

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+mutable_buffer_archetype_(mutable_buffer_archetype_ const& other) = default;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-09.html b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-09.html new file mode 100644 index 0000000..e53cfe2 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-09.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-0b.html b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-0b.html new file mode 100644 index 0000000..602f25c --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-0b.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_

+
+
+
+

Move constructor

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+mutable_buffer_archetype_(mutable_buffer_archetype_&& other) = default;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-0c.html b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-0c.html new file mode 100644 index 0000000..79a0abf --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/2constructor-0c.html @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_::mutable_buffer_archetype_

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Default constructor

+
+
+ +
+ +
+

Copy constructor

+
+
+
+
constexpr
+mutable_buffer_archetype_(mutable_buffer_archetype_ const& other) = default;
+
+
+ +
+

Move constructor

+
+
+
+
constexpr
+mutable_buffer_archetype_(mutable_buffer_archetype_&& other) = default;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/2conversion-0a.html b/preview/reference/boost/capy/mutable_buffer_archetype_/2conversion-0a.html new file mode 100644 index 0000000..436ea5a --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/2conversion-0a.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::operator mutable_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/2conversion-0e.html b/preview/reference/boost/capy/mutable_buffer_archetype_/2conversion-0e.html new file mode 100644 index 0000000..daf4667 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/2conversion-0e.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::operator const_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0a2.html b/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0a2.html new file mode 100644 index 0000000..72f62f0 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0a2.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_::operator=

+
+
+
+

Move assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+mutable_buffer_archetype_&
+operator=(mutable_buffer_archetype_&& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0a3.html b/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0a3.html new file mode 100644 index 0000000..b947161 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0a3.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+ +
+
+
constexpr
+mutable_buffer_archetype_&
+operator=(mutable_buffer_archetype_ const& other) = default;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0c.html b/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0c.html new file mode 100644 index 0000000..def6cc8 --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_archetype_/operator_assign-0c.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_archetype_::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::mutable_buffer_archetype_::operator=

+
+
+
+

Assignment operators

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
constexpr
+mutable_buffer_archetype_&
+operator=(mutable_buffer_archetype_ const& other) = default;
+
+
+ +
+

Move assignment operator

+
+
+ +
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_array.html b/preview/reference/boost/capy/mutable_buffer_array.html new file mode 100644 index 0000000..122902b --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_array.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_array :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/mutable_buffer_pair.html b/preview/reference/boost/capy/mutable_buffer_pair.html new file mode 100644 index 0000000..ae26dac --- /dev/null +++ b/preview/reference/boost/capy/mutable_buffer_pair.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::mutable_buffer_pair :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/prefix.html b/preview/reference/boost/capy/prefix.html new file mode 100644 index 0000000..a7d14cf --- /dev/null +++ b/preview/reference/boost/capy/prefix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::prefix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/prefix_mrdocs_workaround_t.html b/preview/reference/boost/capy/prefix_mrdocs_workaround_t.html new file mode 100644 index 0000000..1345727 --- /dev/null +++ b/preview/reference/boost/capy/prefix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::prefix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/prefix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/prefix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..658d402 --- /dev/null +++ b/preview/reference/boost/capy/prefix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::prefix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/pull_from-04.html b/preview/reference/boost/capy/pull_from-04.html new file mode 100644 index 0000000..86d4860 --- /dev/null +++ b/preview/reference/boost/capy/pull_from-04.html @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + boost::capy::pull_from :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::pull_from

+
+
+
+

Transfer data from a ReadStream to a BufferSink.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io/pull_from.hpp>

+
+
+
+
template<
+    ReadStream Src,
+    BufferSink Sink>
+requires (!ReadSource<Src>)
+io_task<std::size_t>
+pull_from(
+    Src& source,
+    Sink& sink);
+
+
+
+
+
+

Description

+
+
+

This function reads data from the stream directly into the sink's internal buffers using the callee‐owns‐buffers model. The sink provides writable buffers via prepare(), the stream reads into them using read_some(), and the sink commits the data. When the stream signals EOF, commit_eof() is called on the sink to finalize the transfer.

+
+
+

This overload handles partial reads from the stream, committing data incrementally as it arrives. It loops until EOF is encountered or an error occurs.

+
+
+
+
+

Example

+
+
+
+
task<void> transfer_body(ReadStream auto& stream, BufferSink auto& sink)
+{
+    auto [ec, n] = co_await pull_from(stream, sink);
+    if (ec)
+    {
+        // Handle error
+    }
+    // n bytes were transferred
+}
+
+
+
+
+
+

Return Value

+
+
+

A task that yields (std::error_code, std::size_t). On success, ec is default‐constructed (no error) and n is the total number of bytes transferred. On error, ec contains the error code and n is the total number of bytes transferred before the error.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

Src

The source type, must satisfy ReadStream.

Sink

The sink type, must satisfy BufferSink.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

source

The stream to read data from.

sink

The sink to write data to.

+
+
+
+

See Also

+
+
+

ReadStream, BufferSink, push_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/pull_from-07.html b/preview/reference/boost/capy/pull_from-07.html new file mode 100644 index 0000000..493f364 --- /dev/null +++ b/preview/reference/boost/capy/pull_from-07.html @@ -0,0 +1,486 @@ + + + + + + + + + + + + + + boost::capy::pull_from :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::pull_from

+
+
+
+

Transfer data from a ReadSource to a BufferSink.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io/pull_from.hpp>

+
+
+
+
template<
+    ReadSource Src,
+    BufferSink Sink>
+io_task<std::size_t>
+pull_from(
+    Src& source,
+    Sink& sink);
+
+
+
+
+
+

Description

+
+
+

This function reads data from the source directly into the sink's internal buffers using the callee‐owns‐buffers model. The sink provides writable buffers via prepare(), the source reads into them, and the sink commits the data. When the source signals EOF, commit_eof() is called on the sink to finalize the transfer.

+
+
+
+
+

Example

+
+
+
+
task<void> transfer_body(ReadSource auto& source, BufferSink auto& sink)
+{
+    auto [ec, n] = co_await pull_from(source, sink);
+    if (ec)
+    {
+        // Handle error
+    }
+    // n bytes were transferred
+}
+
+
+
+
+
+

Return Value

+
+
+

A task that yields (std::error_code, std::size_t). On success, ec is default‐constructed (no error) and n is the total number of bytes transferred. On error, ec contains the error code and n is the total number of bytes transferred before the error.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

Src

The source type, must satisfy ReadSource.

Sink

The sink type, must satisfy BufferSink.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

source

The source to read data from.

sink

The sink to write data to.

+
+
+
+

See Also

+
+
+

ReadSource, BufferSink, push_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/pull_from-09.html b/preview/reference/boost/capy/pull_from-09.html new file mode 100644 index 0000000..82d3d42 --- /dev/null +++ b/preview/reference/boost/capy/pull_from-09.html @@ -0,0 +1,487 @@ + + + + + + + + + + + + + + boost::capy::pull_from :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::pull_from

+
+
+
+

pull_from overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/io/pull_from.hpp>

+
+
+

Transfer data from a ReadSource to a BufferSink.

+
+
+
+
template<
+    ReadSource Src,
+    BufferSink Sink>
+io_task<std::size_t>
+pull_from(
+    Src& source,
+    Sink& sink);
+
+
+ +
+

Transfer data from a ReadStream to a BufferSink.

+
+
+
+
template<
+    ReadStream Src,
+    BufferSink Sink>
+requires (!ReadSource<Src>)
+io_task<std::size_t>
+pull_from(
+    Src& source,
+    Sink& sink);
+
+
+ +
+
+
+

Return Value

+
+
+

A task that yields (std::error_code, std::size_t). On success, ec is default‐constructed (no error) and n is the total number of bytes transferred. On error, ec contains the error code and n is the total number of bytes transferred before the error.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

Src

The source type, must satisfy ReadSource.

Sink

The sink type, must satisfy BufferSink.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

source

The source to read data from.

sink

The sink to write data to.

+
+
+
+

See Also

+
+
+

ReadSource, BufferSink, push_to

+
+
+

ReadStream, BufferSink, push_to

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/push_to-01.html b/preview/reference/boost/capy/push_to-01.html new file mode 100644 index 0000000..b6c3635 --- /dev/null +++ b/preview/reference/boost/capy/push_to-01.html @@ -0,0 +1,486 @@ + + + + + + + + + + + + + + boost::capy::push_to :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::push_to

+
+
+
+

Transfer data from a BufferSource to a WriteSink.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io/push_to.hpp>

+
+
+
+
template<
+    BufferSource Src,
+    WriteSink Sink>
+io_task<std::size_t>
+push_to(
+    Src& source,
+    Sink& sink);
+
+
+
+
+
+

Description

+
+
+

This function pulls data from the source and writes it to the sink until the source is exhausted or an error occurs. When the source signals completion, write_eof() is called on the sink to finalize the transfer.

+
+
+
+
+

Example

+
+
+
+
task<void> transfer_body(BufferSource auto& source, WriteSink auto& sink)
+{
+    auto [ec, n] = co_await push_to(source, sink);
+    if (ec)
+    {
+        // Handle error
+    }
+    // n bytes were transferred
+}
+
+
+
+
+
+

Return Value

+
+
+

A task that yields (std::error_code, std::size_t). On success, ec is default‐constructed (no error) and n is the total number of bytes transferred. On error, ec contains the error code and n is the total number of bytes transferred before the error.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

Src

The source type, must satisfy BufferSource.

Sink

The sink type, must satisfy WriteSink.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

source

The source to pull data from.

sink

The sink to write data to.

+
+
+
+

See Also

+
+
+

BufferSource, WriteSink

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/push_to-03.html b/preview/reference/boost/capy/push_to-03.html new file mode 100644 index 0000000..3f13aa6 --- /dev/null +++ b/preview/reference/boost/capy/push_to-03.html @@ -0,0 +1,495 @@ + + + + + + + + + + + + + + boost::capy::push_to :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::push_to

+
+
+
+

push_to overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/io/push_to.hpp>

+
+
+

Transfer data from a BufferSource to a WriteSink.

+
+
+
+
template<
+    BufferSource Src,
+    WriteSink Sink>
+io_task<std::size_t>
+push_to(
+    Src& source,
+    Sink& sink);
+
+
+ +
+

Transfer data from a BufferSource to a WriteStream.

+
+
+
+
template<
+    BufferSource Src,
+    WriteStream Stream>
+requires (!WriteSink<Stream>)
+io_task<std::size_t>
+push_to(
+    Src& source,
+    Stream& stream);
+
+
+ +
+
+
+

Return Value

+
+
+

A task that yields (std::error_code, std::size_t). On success, ec is default‐constructed (no error) and n is the total number of bytes transferred. On error, ec contains the error code and n is the total number of bytes transferred before the error.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

Src

The source type, must satisfy BufferSource.

Sink

The sink type, must satisfy WriteSink.

Stream

The stream type, must satisfy WriteStream.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

source

The source to pull data from.

sink

The sink to write data to.

stream

The stream to write data to.

+
+
+
+

See Also

+
+
+

BufferSource, WriteSink

+
+
+

BufferSource, WriteStream, pull_from

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/push_to-0d.html b/preview/reference/boost/capy/push_to-0d.html new file mode 100644 index 0000000..ae577ea --- /dev/null +++ b/preview/reference/boost/capy/push_to-0d.html @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + boost::capy::push_to :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::push_to

+
+
+
+

Transfer data from a BufferSource to a WriteStream.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/io/push_to.hpp>

+
+
+
+
template<
+    BufferSource Src,
+    WriteStream Stream>
+requires (!WriteSink<Stream>)
+io_task<std::size_t>
+push_to(
+    Src& source,
+    Stream& stream);
+
+
+
+
+
+

Description

+
+
+

This function pulls data from the source and writes it to the stream until the source is exhausted or an error occurs. The stream uses write_some() which may perform partial writes, so this function loops until all pulled data is consumed.

+
+
+

Unlike the WriteSink overload, this function does not signal EOF explicitly since WriteStream does not provide a write_eof method. The transfer completes when the source is exhausted.

+
+
+
+
+

Example

+
+
+
+
task<void> transfer_body(BufferSource auto& source, WriteStream auto& stream)
+{
+    auto [ec, n] = co_await push_to(source, stream);
+    if (ec)
+    {
+        // Handle error
+    }
+    // n bytes were transferred
+}
+
+
+
+
+
+

Return Value

+
+
+

A task that yields (std::error_code, std::size_t). On success, ec is default‐constructed (no error) and n is the total number of bytes transferred. On error, ec contains the error code and n is the total number of bytes transferred before the error.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

Src

The source type, must satisfy BufferSource.

Stream

The stream type, must satisfy WriteStream.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

source

The source to pull data from.

stream

The stream to write data to.

+
+
+
+

See Also

+
+
+

BufferSource, WriteStream, pull_from

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/read-0a.html b/preview/reference/boost/capy/read-0a.html new file mode 100644 index 0000000..0784e47 --- /dev/null +++ b/preview/reference/boost/capy/read-0a.html @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + boost::capy::read :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::read

+
+
+
+

Asynchronously read until the buffer sequence is full.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/read.hpp>

+
+
+
+
io_task<std::size_t>
+read(
+    auto& stream,
+    auto const& buffers);
+
+
+
+
+
+

Description

+
+
+

Reads data from the stream by calling read_some repeatedly until the entire buffer sequence is filled or an error occurs.

+
+
+
    +
  • +

    The operation completes when:

    +
  • +
  • +

    The buffer sequence is completely filled

    +
  • +
  • +

    An error occurs (including `cond::eof`)

    +
  • +
  • +

    The operation is cancelled

    +
  • +
+
+
+
+
+

Cancellation

+
+
+

Supports cancellation via stop_token propagated through the IoAwaitable protocol. When cancelled, returns with cond::canceled.

+
+
+
    +
  • +

    `cond::eof` ‐ Stream reached end before buffer was filled

    +
  • +
  • +

    `cond::canceled` ‐ Operation was cancelled

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<> read_message( ReadStream auto& stream )
+{
+    char header[16];
+    auto [ec, n] = co_await read( stream, mutable_buffer( header ) );
+    if( ec == cond::eof )
+        co_return;  // Connection closed
+    if( ec )
+        detail::throw_system_error( ec );
+    // header contains exactly 16 bytes
+}
+
+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code, std::size_t). On success, n equals buffer_size(buffers). On error, n is the number of bytes read before the error. Compare error codes to conditions:

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to read from. The caller retains ownership.

buffers

The buffer sequence to fill. The caller retains ownership and must ensure validity until the operation completes.

+
+
+
+

See Also

+
+
+

read_some, ReadStream, MutableBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/read-0c.html b/preview/reference/boost/capy/read-0c.html new file mode 100644 index 0000000..b1de5e7 --- /dev/null +++ b/preview/reference/boost/capy/read-0c.html @@ -0,0 +1,552 @@ + + + + + + + + + + + + + + boost::capy::read :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::read

+
+
+
+

Asynchronously read all data from a stream into a dynamic buffer.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/read.hpp>

+
+
+
+
io_task<std::size_t>
+read(
+    auto& stream,
+    auto&& buffers,
+    std::size_t initial_amount = 2048);
+
+
+
+
+
+

Description

+
+
+

Reads data by calling read_some repeatedly until EOF is reached or an error occurs. Data is appended using prepare/commit semantics. The buffer grows with 1.5x factor when filled.

+
+
+
    +
  • +

    The operation completes when:

    +
  • +
  • +

    End‐of‐stream is reached (`cond::eof`)

    +
  • +
  • +

    An error occurs

    +
  • +
  • +

    The operation is cancelled

    +
  • +
+
+
+
+
+

Cancellation

+
+
+

Supports cancellation via stop_token propagated through the IoAwaitable protocol. When cancelled, returns with cond::canceled.

+
+
+
    +
  • +

    `cond::canceled` ‐ Operation was cancelled

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<std::string> read_body( ReadStream auto& stream )
+{
+    std::string body;
+    auto [ec, n] = co_await read( stream, string_dynamic_buffer( &body ) );
+    if( ec )
+        detail::throw_system_error( ec );
+    return body;
+}
+
+
+
+

Asynchronously read all data from a source into a dynamic buffer.

+
+
+

Reads data by calling source.read repeatedly until EOF is reached or an error occurs. Data is appended using prepare/commit semantics. The buffer grows with 1.5x factor when filled.

+
+
+
    +
  • +

    The operation completes when:

    +
  • +
  • +

    End‐of‐stream is reached (`cond::eof`)

    +
  • +
  • +

    An error occurs

    +
  • +
  • +

    The operation is cancelled

    +
  • +
+
+
+
+
+

Cancellation

+
+
+

Supports cancellation via stop_token propagated through the IoAwaitable protocol. When cancelled, returns with cond::canceled.

+
+
+
    +
  • +

    `cond::canceled` ‐ Operation was cancelled

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<std::string> read_body( ReadSource auto& source )
+{
+    std::string body;
+    auto [ec, n] = co_await read( source, string_dynamic_buffer( &body ) );
+    if( ec )
+        detail::throw_system_error( ec );
+    return body;
+}
+
+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code, std::size_t). On success (EOF), ec is clear and n is total bytes read. On error, n is bytes read before the error. Compare error codes to conditions:

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to read from. The caller retains ownership.

buffers

The dynamic buffer to append data to. Must remain valid until the operation completes.

initial_amount

Initial bytes to prepare (default 2048).

source

The source to read from. The caller retains ownership.

+
+
+
+

See Also

+
+
+

read_some, ReadStream, DynamicBufferParam

+
+
+

ReadSource, DynamicBufferParam

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/read-0e.html b/preview/reference/boost/capy/read-0e.html new file mode 100644 index 0000000..ebf9b70 --- /dev/null +++ b/preview/reference/boost/capy/read-0e.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + boost::capy::read :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::read

+
+
+
+

read overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/read.hpp>

+
+
+

Asynchronously read until the buffer sequence is full.

+
+
+
+
io_task<std::size_t>
+read(
+    auto& stream,
+    auto const& buffers);
+
+
+ +
+

Asynchronously read all data from a stream into a dynamic buffer.

+
+
+
+
io_task<std::size_t>
+read(
+    auto& stream,
+    auto&& buffers,
+    std::size_t initial_amount = 2048);
+
+
+ +
+
+
+

Return Value

+
+
+
    +
  • +

    An awaitable yielding (error_code, std::size_t). On success, n equals buffer_size(buffers). On error, n is the number of bytes read before the error. Compare error codes to conditions:

    +
  • +
  • +

    An awaitable yielding (error_code, std::size_t). On success (EOF), ec is clear and n is total bytes read. On error, n is bytes read before the error. Compare error codes to conditions:

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to read from. The caller retains ownership.

buffers

The buffer sequence to fill. The caller retains ownership and must ensure validity until the operation completes.

initial_amount

Initial bytes to prepare (default 2048).

source

The source to read from. The caller retains ownership.

+
+
+
+

See Also

+
+
+

read_some, ReadStream, MutableBufferSequence

+
+
+

read_some, ReadStream, DynamicBufferParam

+
+
+

ReadSource, DynamicBufferParam

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/read_until-0c.html b/preview/reference/boost/capy/read_until-0c.html new file mode 100644 index 0000000..63fe7cd --- /dev/null +++ b/preview/reference/boost/capy/read_until-0c.html @@ -0,0 +1,523 @@ + + + + + + + + + + + + + + boost::capy::read_until :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::read_until

+
+
+
+

Asynchronously read until a match condition is satisfied.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/read_until.hpp>

+
+
+
+
template<
+    ReadStream Stream,
+    class B,
+    MatchCondition M>
+requires DynamicBufferParam<B&&>
+auto
+read_until(
+    Stream& stream,
+    B&& buffers,
+    M match,
+    std::size_t initial_amount = 2048);
+
+
+
+
+
+

Description

+
+
+

Reads data from the stream into the dynamic buffer until the match condition returns a valid position. Implemented using read_some. If the match condition is already satisfied by existing buffer data, returns immediately without I/O.

+
+
+
    +
  • +

    The operation completes when:

    +
  • +
  • +

    The match condition returns a valid position

    +
  • +
  • +

    End‐of‐stream is reached (`cond::eof`)

    +
  • +
  • +

    The buffer's `max_size()` is reached (`cond::not_found`)

    +
  • +
  • +

    An error occurs

    +
  • +
  • +

    The operation is cancelled

    +
  • +
+
+
+
+
+

Cancellation

+
+
+

Supports cancellation via stop_token propagated through the IoAwaitable protocol. When cancelled, returns with cond::canceled.

+
+
+
    +
  • +

    `cond::eof` ‐ EOF before match; `n` is buffer size

    +
  • +
  • +

    `cond::not_found` ‐ `max_size()` reached before match

    +
  • +
  • +

    `cond::canceled` ‐ Operation was cancelled

    +
  • +
+
+
+
+
+

Example

+
+
+
+
    task<> read_http_header( ReadStream auto& stream )
+    {
+        std::string header;
+        auto [ec, n] = co_await read_until(
+            stream,
+            string_dynamic_buffer( &header ),
+            []( std::string_view data, std::size_t* hint ) {
+                auto pos = data.find( "\r\n\r\n" );
+                if( pos != std::string_view::npos )
+                    return pos + 4;
+                if( hint )
+hint = 3;  // partial "\r\n\r" possible
+                return std::string_view::npos;
+            } );
+        if( ec )
+            detail::throw_system_error( ec );
+        // header contains data through "\r\n\r\n"
+    }
+
+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code, std::size_t). On success, n is the position returned by the match condition (bytes up to and including the matched delimiter). Compare error codes to conditions:

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to read from. The caller retains ownership.

buffers

The dynamic buffer to append data to. Must remain valid until the operation completes.

match

The match condition callable. Copied into the awaitable.

initial_amount

Initial bytes to read per iteration (default 2048). Grows by 1.5x when filled.

+
+
+
+

See Also

+
+
+

read_some, MatchCondition, DynamicBufferParam

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/read_until-0d.html b/preview/reference/boost/capy/read_until-0d.html new file mode 100644 index 0000000..d24fa18 --- /dev/null +++ b/preview/reference/boost/capy/read_until-0d.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + boost::capy::read_until :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::read_until

+
+
+
+

Asynchronously read until a delimiter string is found.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/read_until.hpp>

+
+
+
+
template<
+    ReadStream Stream,
+    class B>
+requires DynamicBufferParam<B&&>
+auto
+read_until(
+    Stream& stream,
+    B&& buffers,
+    std::string_view delim,
+    std::size_t initial_amount = 2048);
+
+
+
+
+
+

Description

+
+
+

Reads data from the stream until the delimiter is found. This is a convenience overload equivalent to calling read_until with match_delim{delim}. If the delimiter already exists in the buffer, returns immediately without I/O.

+
+
+
    +
  • +

    The operation completes when:

    +
  • +
  • +

    The delimiter string is found

    +
  • +
  • +

    End‐of‐stream is reached (`cond::eof`)

    +
  • +
  • +

    The buffer's `max_size()` is reached (`cond::not_found`)

    +
  • +
  • +

    An error occurs

    +
  • +
  • +

    The operation is cancelled

    +
  • +
+
+
+
+
+

Cancellation

+
+
+

Supports cancellation via stop_token propagated through the IoAwaitable protocol. When cancelled, returns with cond::canceled.

+
+
+
    +
  • +

    `cond::eof` ‐ EOF before delimiter; `n` is buffer size

    +
  • +
  • +

    `cond::not_found` ‐ `max_size()` reached before delimiter

    +
  • +
  • +

    `cond::canceled` ‐ Operation was cancelled

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<std::string> read_line( ReadStream auto& stream )
+{
+    std::string line;
+    auto [ec, n] = co_await read_until(
+        stream, string_dynamic_buffer( &line ), "\r\n" );
+    if( ec == cond::eof )
+        co_return line;  // partial line at EOF
+    if( ec )
+        detail::throw_system_error( ec );
+    line.resize( n - 2 );  // remove "\r\n"
+    co_return line;
+}
+
+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code, std::size_t). On success, n is bytes up to and including the delimiter. Compare error codes to conditions:

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to read from. The caller retains ownership.

buffers

The dynamic buffer to append data to. Must remain valid until the operation completes.

delim

The delimiter string to search for.

initial_amount

Initial bytes to read per iteration (default 2048). Grows by 1.5x when filled.

+
+
+
+

See Also

+
+
+

read_until, match_delim, DynamicBufferParam

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/read_until-0f.html b/preview/reference/boost/capy/read_until-0f.html new file mode 100644 index 0000000..10cfa61 --- /dev/null +++ b/preview/reference/boost/capy/read_until-0f.html @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + boost::capy::read_until :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::read_until

+
+
+
+

read_until overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/read_until.hpp>

+
+
+

Asynchronously read until a delimiter string is found.

+
+
+
+
template<
+    ReadStream Stream,
+    class B>
+requires DynamicBufferParam<B&&>
+auto
+read_until(
+    Stream& stream,
+    B&& buffers,
+    std::string_view delim,
+    std::size_t initial_amount = 2048);
+
+
+ +
+

Asynchronously read until a match condition is satisfied.

+
+
+
+
template<
+    ReadStream Stream,
+    class B,
+    MatchCondition M>
+requires DynamicBufferParam<B&&>
+auto
+read_until(
+    Stream& stream,
+    B&& buffers,
+    M match,
+    std::size_t initial_amount = 2048);
+
+
+ +
+
+
+

Return Value

+
+
+
    +
  • +

    An awaitable yielding (error_code, std::size_t). On success, n is bytes up to and including the delimiter. Compare error codes to conditions:

    +
  • +
  • +

    An awaitable yielding (error_code, std::size_t). On success, n is the position returned by the match condition (bytes up to and including the matched delimiter). Compare error codes to conditions:

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to read from. The caller retains ownership.

buffers

The dynamic buffer to append data to. Must remain valid until the operation completes.

delim

The delimiter string to search for.

initial_amount

Initial bytes to read per iteration (default 2048). Grows by 1.5x when filled.

match

The match condition callable. Copied into the awaitable.

+
+
+
+

See Also

+
+
+

read_until, match_delim, DynamicBufferParam

+
+
+

read_some, MatchCondition, DynamicBufferParam

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-00.html b/preview/reference/boost/capy/ready-00.html new file mode 100644 index 0000000..a5ea60b --- /dev/null +++ b/preview/reference/boost/capy/ready-00.html @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for a failed io_result.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
immediate<io_result>
+ready(std::error_code ec) noexcept;
+
+
+
+
+
+

Description

+
+
+

This helper creates an immediate wrapping an io_result with an error code.

+
+
+
+
+

Example

+
+
+
+
immediate<io_result<std::size_t>>
+write(const_buffer buf)
+{
+    auto ec = write_sync(buf);
+    if(ec)
+        return ready(ec, std::size_t{0});
+    return ready(buffer_size(buf));
+}
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing a failed io_result.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ec

The error code.

+
+
+
+

See Also

+
+
+

immediate, io_result

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-01.html b/preview/reference/boost/capy/ready-01.html new file mode 100644 index 0000000..c62e7b6 --- /dev/null +++ b/preview/reference/boost/capy/ready-01.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for a successful io_result with one value.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<class T1>
+immediate<io_result<T1>>
+ready(T1 t1);
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing io_result<T1>{{}, t1}.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

t1

The result value.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-05.html b/preview/reference/boost/capy/ready-05.html new file mode 100644 index 0000000..2a98650 --- /dev/null +++ b/preview/reference/boost/capy/ready-05.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for a successful io_result with three values.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<
+    class T1,
+    class T2,
+    class T3>
+immediate<io_result<T1, T2, T3>>
+ready(
+    T1 t1,
+    T2 t2,
+    T3 t3);
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing io_result<T1,T2,T3>{{}, t1, t2, t3}.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

t1

The first result value.

t2

The second result value.

t3

The third result value.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-06.html b/preview/reference/boost/capy/ready-06.html new file mode 100644 index 0000000..795bfb8 --- /dev/null +++ b/preview/reference/boost/capy/ready-06.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for a successful io_result with two values.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<
+    class T1,
+    class T2>
+immediate<io_result<T1, T2>>
+ready(
+    T1 t1,
+    T2 t2);
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing io_result<T1,T2>{{}, t1, t2}.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

t1

The first result value.

t2

The second result value.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-0b.html b/preview/reference/boost/capy/ready-0b.html new file mode 100644 index 0000000..1168a31 --- /dev/null +++ b/preview/reference/boost/capy/ready-0b.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for an io_result with error and three values.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<
+    class T1,
+    class T2,
+    class T3>
+immediate<io_result<T1, T2, T3>>
+ready(
+    std::error_code ec,
+    T1 t1,
+    T2 t2,
+    T3 t3);
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing io_result<T1,T2,T3>{ec, t1, t2, t3}.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ec

The error code.

t1

The first result value.

t2

The second result value.

t3

The third result value.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-0c.html b/preview/reference/boost/capy/ready-0c.html new file mode 100644 index 0000000..8d62354 --- /dev/null +++ b/preview/reference/boost/capy/ready-0c.html @@ -0,0 +1,581 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

ready overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+

Create an immediate awaitable for a successful io_result.

+
+
+
+
immediate<io_result>
+ready() noexcept;
+
+
+ +
+

Create an immediate awaitable for a failed io_result.

+
+
+
+
immediate<io_result>
+ready(std::error_code ec) noexcept;
+
+
+ +
+

Create an immediate awaitable for a successful io_result with one value.

+
+
+
+
template<class T1>
+immediate<io_result<T1>>
+ready(T1 t1);
+
+
+ +
+

Create an immediate awaitable for an io_result with error and one value.

+
+
+
+
template<class T1>
+immediate<io_result<T1>>
+ready(
+    std::error_code ec,
+    T1 t1);
+
+
+ +
+

Create an immediate awaitable for a successful io_result with two values.

+
+
+
+
template<
+    class T1,
+    class T2>
+immediate<io_result<T1, T2>>
+ready(
+    T1 t1,
+    T2 t2);
+
+
+ +
+

Create an immediate awaitable for an io_result with error and two values.

+
+
+
+
template<
+    class T1,
+    class T2>
+immediate<io_result<T1, T2>>
+ready(
+    std::error_code ec,
+    T1 t1,
+    T2 t2);
+
+
+ +
+

Create an immediate awaitable for a successful io_result with three values.

+
+
+
+
template<
+    class T1,
+    class T2,
+    class T3>
+immediate<io_result<T1, T2, T3>>
+ready(
+    T1 t1,
+    T2 t2,
+    T3 t3);
+
+
+ +
+

Create an immediate awaitable for an io_result with error and three values.

+
+
+
+
template<
+    class T1,
+    class T2,
+    class T3>
+immediate<io_result<T1, T2, T3>>
+ready(
+    std::error_code ec,
+    T1 t1,
+    T2 t2,
+    T3 t3);
+
+
+ +
+
+
+

Return Value

+
+
+
    +
  • +

    An immediate awaitable containing a successful io_result.

    +
  • +
  • +

    An immediate awaitable containing a failed io_result.

    +
  • +
  • +

    An immediate awaitable containing io_result<T1>{{}, t1}.

    +
  • +
  • +

    An immediate awaitable containing io_result<T1>{ec, t1}.

    +
  • +
  • +

    An immediate awaitable containing io_result<T1,T2>{{}, t1, t2}.

    +
  • +
  • +

    An immediate awaitable containing io_result<T1,T2>{ec, t1, t2}.

    +
  • +
  • +

    An immediate awaitable containing io_result<T1,T2,T3>{{}, t1, t2, t3}.

    +
  • +
  • +

    An immediate awaitable containing io_result<T1,T2,T3>{ec, t1, t2, t3}.

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ec

The error code.

t1

The result value.

t2

The second result value.

t3

The third result value.

+
+
+
+

See Also

+
+
+

immediate, io_result

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-0d0.html b/preview/reference/boost/capy/ready-0d0.html new file mode 100644 index 0000000..05ad2ed --- /dev/null +++ b/preview/reference/boost/capy/ready-0d0.html @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for an io_result with error and two values.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<
+    class T1,
+    class T2>
+immediate<io_result<T1, T2>>
+ready(
+    std::error_code ec,
+    T1 t1,
+    T2 t2);
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing io_result<T1,T2>{ec, t1, t2}.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

ec

The error code.

t1

The first result value.

t2

The second result value.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-0df.html b/preview/reference/boost/capy/ready-0df.html new file mode 100644 index 0000000..7bd3b14 --- /dev/null +++ b/preview/reference/boost/capy/ready-0df.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for a successful io_result.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
immediate<io_result>
+ready() noexcept;
+
+
+
+
+
+

Description

+
+
+

This helper creates an immediate wrapping an io_result with no error and the provided values.

+
+
+
+
+

Example

+
+
+
+
immediate<io_result<std::size_t>>
+write(const_buffer buf)
+{
+    auto n = write_sync(buf);
+    return ready(n);  // success with n bytes
+}
+
+immediate<io_result<>>
+connect()
+{
+    connect_sync();
+    return ready();  // void success
+}
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing a successful io_result.

+
+
+
+
+

See Also

+
+
+

immediate, io_result

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/ready-0e.html b/preview/reference/boost/capy/ready-0e.html new file mode 100644 index 0000000..4bc67c6 --- /dev/null +++ b/preview/reference/boost/capy/ready-0e.html @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + boost::capy::ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::ready

+
+
+
+

Create an immediate awaitable for an io_result with error and one value.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/immediate.hpp>

+
+
+
+
template<class T1>
+immediate<io_result<T1>>
+ready(
+    std::error_code ec,
+    T1 t1);
+
+
+
+
+
+

Return Value

+
+
+

An immediate awaitable containing io_result<T1>{ec, t1}.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ec

The error code.

t1

The result value.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource.html b/preview/reference/boost/capy/recycling_memory_resource.html new file mode 100644 index 0000000..605d91c --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource.html @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::recycling_memory_resource

+
+

Synopsis

+
+ +
+
+
class recycling_memory_resource
+    : public std::pmr::memory_resource
+
+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

std::pmr::memory_resource

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

~recycling_memory_resource [destructor] [virtual]

Destructor

allocate

allocate_fast

Allocate without virtual dispatch.

deallocate

deallocate_fast

Deallocate without virtual dispatch.

is_equal

+
+
+
+

Protected Member Functions

+
+ +++ + + + + + + + + + + + + + + +

Name

do_allocate [virtual]

do_deallocate [virtual]

do_is_equal [virtual]

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/2destructor.html b/preview/reference/boost/capy/recycling_memory_resource/2destructor.html new file mode 100644 index 0000000..0197f16 --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/2destructor.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::~recycling_memory_resource :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/allocate.html b/preview/reference/boost/capy/recycling_memory_resource/allocate.html new file mode 100644 index 0000000..3184d4a --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/allocate.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::allocate :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/allocate_fast.html b/preview/reference/boost/capy/recycling_memory_resource/allocate_fast.html new file mode 100644 index 0000000..d1d8bb3 --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/allocate_fast.html @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::allocate_fast :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::recycling_memory_resource::allocate_fast

+
+
+
+

Allocate without virtual dispatch.

+
+
+
+
+

Synopsis

+
+ +
+
+
void*
+allocate_fast(
+    std::size_t bytes,
+    std::size_t);
+
+
+
+
+
+

Description

+
+
+

Handles the fast path inline (thread‐local bucket pop) and falls through to the slow path for global pool or heap allocation.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/deallocate.html b/preview/reference/boost/capy/recycling_memory_resource/deallocate.html new file mode 100644 index 0000000..7c47fe1 --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/deallocate.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::deallocate :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/deallocate_fast.html b/preview/reference/boost/capy/recycling_memory_resource/deallocate_fast.html new file mode 100644 index 0000000..4cdace2 --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/deallocate_fast.html @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::deallocate_fast :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::recycling_memory_resource::deallocate_fast

+
+
+
+

Deallocate without virtual dispatch.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+deallocate_fast(
+    void* p,
+    std::size_t bytes,
+    std::size_t);
+
+
+
+
+
+

Description

+
+
+

Handles the fast path inline (thread‐local bucket push) and falls through to the slow path for global pool or heap deallocation.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/do_allocate.html b/preview/reference/boost/capy/recycling_memory_resource/do_allocate.html new file mode 100644 index 0000000..b8def59 --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/do_allocate.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::do_allocate :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/do_deallocate.html b/preview/reference/boost/capy/recycling_memory_resource/do_deallocate.html new file mode 100644 index 0000000..b1d286e --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/do_deallocate.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::do_deallocate :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/do_is_equal.html b/preview/reference/boost/capy/recycling_memory_resource/do_is_equal.html new file mode 100644 index 0000000..4e7cfae --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/do_is_equal.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::do_is_equal :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/recycling_memory_resource/is_equal.html b/preview/reference/boost/capy/recycling_memory_resource/is_equal.html new file mode 100644 index 0000000..1f2caef --- /dev/null +++ b/preview/reference/boost/capy/recycling_memory_resource/is_equal.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + boost::capy::recycling_memory_resource::is_equal :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/remove_prefix.html b/preview/reference/boost/capy/remove_prefix.html new file mode 100644 index 0000000..18fa7ac --- /dev/null +++ b/preview/reference/boost/capy/remove_prefix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::remove_prefix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/remove_prefix_mrdocs_workaround_t.html b/preview/reference/boost/capy/remove_prefix_mrdocs_workaround_t.html new file mode 100644 index 0000000..538174f --- /dev/null +++ b/preview/reference/boost/capy/remove_prefix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::remove_prefix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::remove_prefix_mrdocs_workaround_t

+
+
+
+

Remove n bytes from the beginning of a buffer sequence

+
+
+
+
+

Synopsis

+
+ +
+
+
struct remove_prefix_mrdocs_workaround_t;
+
+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/remove_prefix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/remove_prefix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..fce3c35 --- /dev/null +++ b/preview/reference/boost/capy/remove_prefix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::remove_prefix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/remove_suffix.html b/preview/reference/boost/capy/remove_suffix.html new file mode 100644 index 0000000..78c690a --- /dev/null +++ b/preview/reference/boost/capy/remove_suffix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::remove_suffix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/remove_suffix_mrdocs_workaround_t.html b/preview/reference/boost/capy/remove_suffix_mrdocs_workaround_t.html new file mode 100644 index 0000000..4f19fec --- /dev/null +++ b/preview/reference/boost/capy/remove_suffix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::remove_suffix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/remove_suffix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/remove_suffix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..3057e07 --- /dev/null +++ b/preview/reference/boost/capy/remove_suffix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::remove_suffix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/run-025.html b/preview/reference/boost/capy/run-025.html new file mode 100644 index 0000000..5c85d4d --- /dev/null +++ b/preview/reference/boost/capy/run-025.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Run a task with stop token and standard allocator.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template</* implementation-defined */ Alloc>
+[[nodiscard]]
+auto
+run(
+    std::stop_token st,
+    Alloc alloc);
+
+
+
+
+
+

Description

+
+
+

The task inherits the caller's executor.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

st

The stop token for cooperative cancellation.

alloc

The allocator for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-02e.html b/preview/reference/boost/capy/run-02e.html new file mode 100644 index 0000000..f90edec --- /dev/null +++ b/preview/reference/boost/capy/run-02e.html @@ -0,0 +1,590 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

run overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+

Run a task with a custom stop token.

+
+
+
+
[[nodiscard]]
+auto
+run(std::stop_token st);
+
+
+ +
+

Run a task with a custom memory resource.

+
+
+
+
[[nodiscard]]
+auto
+run(std::pmr::memory_resource* mr);
+
+
+ +
+

Bind a task to execute on a specific executor.

+
+
+
+
template</* implementation-defined */ Ex>
+[[nodiscard]]
+auto
+run(Ex ex);
+
+
+ +
+

Run a task with stop token and memory resource.

+
+
+
+
[[nodiscard]]
+auto
+run(
+    std::stop_token st,
+    std::pmr::memory_resource* mr);
+
+
+ +
+

Bind a task to an executor with a stop token.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::stop_token st);
+
+
+ +
+

Bind a task to an executor with a memory resource.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::pmr::memory_resource* mr);
+
+
+ +
+

Run a task with stop token and standard allocator.

+
+
+
+
template</* implementation-defined */ Alloc>
+[[nodiscard]]
+auto
+run(
+    std::stop_token st,
+    Alloc alloc);
+
+
+ +
+

Bind a task to an executor with a standard allocator.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    Alloc alloc);
+
+
+ +
+

Bind a task to an executor with stop token and memory resource.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr);
+
+
+ +
+

Bind a task to an executor with stop token and standard allocator.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::stop_token st,
+    Alloc alloc);
+
+
+ +
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

ex

The executor on which the task should run.

alloc

The allocator for frame allocation.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-03.html b/preview/reference/boost/capy/run-03.html new file mode 100644 index 0000000..d86592d --- /dev/null +++ b/preview/reference/boost/capy/run-03.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Run a task with a custom memory resource.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
[[nodiscard]]
+auto
+run(std::pmr::memory_resource* mr);
+
+
+
+
+
+

Description

+
+
+

The task inherits the caller's executor. The memory resource is used for nested frame allocations.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

mr

The memory resource for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-04.html b/preview/reference/boost/capy/run-04.html new file mode 100644 index 0000000..135a544 --- /dev/null +++ b/preview/reference/boost/capy/run-04.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Run a task with stop token and memory resource.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
[[nodiscard]]
+auto
+run(
+    std::stop_token st,
+    std::pmr::memory_resource* mr);
+
+
+
+
+
+

Description

+
+
+

The task inherits the caller's executor.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-055.html b/preview/reference/boost/capy/run-055.html new file mode 100644 index 0000000..a3417d8 --- /dev/null +++ b/preview/reference/boost/capy/run-055.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Bind a task to an executor with stop token and standard allocator.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::stop_token st,
+    Alloc alloc);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor on which the task should run.

st

The stop token for cooperative cancellation.

alloc

The allocator for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-056.html b/preview/reference/boost/capy/run-056.html new file mode 100644 index 0000000..b601fde --- /dev/null +++ b/preview/reference/boost/capy/run-056.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Bind a task to an executor with a stop token.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::stop_token st);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor on which the task should run.

st

The stop token for cooperative cancellation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-058.html b/preview/reference/boost/capy/run-058.html new file mode 100644 index 0000000..b7d56fe --- /dev/null +++ b/preview/reference/boost/capy/run-058.html @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Bind a task to an executor with a standard allocator.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    Alloc alloc);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor on which the task should run.

alloc

The allocator for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-07.html b/preview/reference/boost/capy/run-07.html new file mode 100644 index 0000000..1d9334a --- /dev/null +++ b/preview/reference/boost/capy/run-07.html @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Bind a task to execute on a specific executor.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template</* implementation-defined */ Ex>
+[[nodiscard]]
+auto
+run(Ex ex);
+
+
+
+
+
+

Description

+
+
+

Returns a wrapper that accepts a task and produces an awaitable. When co_awaited, the task runs on the specified executor.

+
+
+
+
+

Example

+
+
+
+
co_await run(other_executor)(my_task());
+
+
+
+

Run a task with a custom standard allocator.

+
+
+

The task inherits the caller's executor. The allocator is used for nested frame allocations.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor on which the task should run.

alloc

The allocator for frame allocation.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-09.html b/preview/reference/boost/capy/run-09.html new file mode 100644 index 0000000..57d3d7c --- /dev/null +++ b/preview/reference/boost/capy/run-09.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Run a task with a custom stop token.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
[[nodiscard]]
+auto
+run(std::stop_token st);
+
+
+
+
+
+

Description

+
+
+

The task inherits the caller's executor. Only the stop token is overridden.

+
+
+
+
+

Example

+
+
+
+
std::stop_source source;
+co_await run(source.get_token())(cancellable_task());
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

st

The stop token for cooperative cancellation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-0e6.html b/preview/reference/boost/capy/run-0e6.html new file mode 100644 index 0000000..efd7d4f --- /dev/null +++ b/preview/reference/boost/capy/run-0e6.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Bind a task to an executor with a memory resource.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::pmr::memory_resource* mr);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor on which the task should run.

mr

The memory resource for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run-0e8.html b/preview/reference/boost/capy/run-0e8.html new file mode 100644 index 0000000..c4373da --- /dev/null +++ b/preview/reference/boost/capy/run-0e8.html @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + boost::capy::run :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run

+
+
+
+

Bind a task to an executor with stop token and memory resource.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task for execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor on which the task should run.

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-00.html b/preview/reference/boost/capy/run_async-00.html new file mode 100644 index 0000000..3df022f --- /dev/null +++ b/preview/reference/boost/capy/run_async-00.html @@ -0,0 +1,443 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with custom memory resource.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::pmr::memory_resource* mr);
+
+
+
+
+
+

Description

+
+
+

The memory resource is used for coroutine frame allocation. The caller is responsible for ensuring the memory resource outlives all tasks.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

mr

The memory resource for frame allocation.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-01.html b/preview/reference/boost/capy/run_async-01.html new file mode 100644 index 0000000..64dceca --- /dev/null +++ b/preview/reference/boost/capy/run_async-01.html @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token and memory resource.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-034.html b/preview/reference/boost/capy/run_async-034.html new file mode 100644 index 0000000..96e8e4c --- /dev/null +++ b/preview/reference/boost/capy/run_async-034.html @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token and result handler.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    H1 h1);
+
+
+
+
+
+

Description

+
+
+

The stop token is propagated to the task for cooperative cancellation. The handler h1 is called with the result on success, and optionally with exception_ptr if it accepts that type.

+
+
+

Asynchronously launch a lazy task with stop token and allocator.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

h1

The handler to invoke with the result (and optionally exception).

alloc

The allocator for frame allocation (copied and stored).

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-039.html b/preview/reference/boost/capy/run_async-039.html new file mode 100644 index 0000000..5ade832 --- /dev/null +++ b/preview/reference/boost/capy/run_async-039.html @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with separate result and error handlers.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    H1 h1,
+    H2 h2);
+
+
+
+
+
+

Description

+
+
+

The handler h1 is called with the task's result on success. The handler h2 is called with the exception_ptr on failure.

+
+
+
+
+

Thread Safety

+
+
+

The handlers may be called from any thread where the executor schedules work.

+
+
+
+
+

Example

+
+
+
+
run_async(ex,
+    [](int result) { std::cout << "Got: " << result << "\n"; },
+    [](std::exception_ptr ep) {
+        try { std::rethrow_exception(ep); }
+        catch (std::exception const& e) {
+            std::cout << "Error: " << e.what() << "\n";
+        }
+    }
+)(compute_value());
+
+
+
+

Asynchronously launch a lazy task with allocator and handler.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

h1

The handler to invoke with the result on success.

h2

The handler to invoke with the exception on failure.

alloc

The allocator for frame allocation (copied and stored).

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-03d.html b/preview/reference/boost/capy/run_async-03d.html new file mode 100644 index 0000000..19e6043 --- /dev/null +++ b/preview/reference/boost/capy/run_async-03d.html @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with a result handler.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    H1 h1);
+
+
+
+
+
+

Description

+
+
+

The handler h1 is called with the task's result on success. If h1 is also invocable with std::exception_ptr, it handles exceptions too. Otherwise, exceptions are rethrown.

+
+
+
+
+

Thread Safety

+
+
+

The handler may be called from any thread where the executor schedules work.

+
+
+
+
+

Example

+
+
+
+
// Handler for result only (exceptions rethrown)
+run_async(ex, [](int result) {
+    std::cout << "Got: " << result << "\n";
+})(compute_value());
+
+// Overloaded handler for both result and exception
+run_async(ex, overloaded{
+    [](int result) { std::cout << "Got: " << result << "\n"; },
+    [](std::exception_ptr) { std::cout << "Failed\n"; }
+})(compute_value());
+
+
+
+

Asynchronously launch a lazy task with custom allocator.

+
+
+

The allocator is wrapped in a frame_memory_resource and stored in the run_async_trampoline, ensuring it outlives all coroutine frames.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

h1

The handler to invoke with the result (and optionally exception).

alloc

The allocator for frame allocation (copied and stored).

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-05.html b/preview/reference/boost/capy/run_async-05.html new file mode 100644 index 0000000..398b9f4 --- /dev/null +++ b/preview/reference/boost/capy/run_async-05.html @@ -0,0 +1,448 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with memory resource and handlers.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::pmr::memory_resource* mr,
+    H1 h1,
+    H2 h2);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

mr

The memory resource for frame allocation.

h1

The handler to invoke with the result on success.

h2

The handler to invoke with the exception on failure.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-06.html b/preview/reference/boost/capy/run_async-06.html new file mode 100644 index 0000000..e335fda --- /dev/null +++ b/preview/reference/boost/capy/run_async-06.html @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token and separate handlers.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    H1 h1,
+    H2 h2);
+
+
+
+
+
+

Description

+
+
+

The stop token is propagated to the task for cooperative cancellation. The handler h1 is called on success, h2 on failure.

+
+
+

Asynchronously launch a lazy task with stop token, allocator, and handler.

+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

h1

The handler to invoke with the result on success.

h2

The handler to invoke with the exception on failure.

alloc

The allocator for frame allocation (copied and stored).

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-07.html b/preview/reference/boost/capy/run_async-07.html new file mode 100644 index 0000000..7ae8ef2 --- /dev/null +++ b/preview/reference/boost/capy/run_async-07.html @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token, allocator, and handlers.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    Alloc alloc,
+    H1 h1,
+    H2 h2);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

alloc

The allocator for frame allocation (copied and stored).

h1

The handler to invoke with the result on success.

h2

The handler to invoke with the exception on failure.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-086.html b/preview/reference/boost/capy/run_async-086.html new file mode 100644 index 0000000..17f79ca --- /dev/null +++ b/preview/reference/boost/capy/run_async-086.html @@ -0,0 +1,453 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token, memory resource, and handlers.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr,
+    H1 h1,
+    H2 h2);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

h1

The handler to invoke with the result on success.

h2

The handler to invoke with the exception on failure.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-08e.html b/preview/reference/boost/capy/run_async-08e.html new file mode 100644 index 0000000..7edb4ae --- /dev/null +++ b/preview/reference/boost/capy/run_async-08e.html @@ -0,0 +1,463 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token support.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st);
+
+
+
+
+
+

Description

+
+
+

The stop token is propagated to the task, enabling cooperative cancellation. With no handlers, the result is discarded and exceptions are rethrown.

+
+
+
+
+

Thread Safety

+
+
+

The wrapper may be called from any thread where the executor schedules work.

+
+
+
+
+

Example

+
+
+
+
std::stop_source source;
+run_async(ex, source.get_token())(cancellable_task());
+// Later: source.request_stop();
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-0c.html b/preview/reference/boost/capy/run_async-0c.html new file mode 100644 index 0000000..b6d2ab4 --- /dev/null +++ b/preview/reference/boost/capy/run_async-0c.html @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with allocator and handlers.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    Alloc alloc,
+    H1 h1,
+    H2 h2);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

alloc

The allocator for frame allocation (copied and stored).

h1

The handler to invoke with the result on success.

h2

The handler to invoke with the exception on failure.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-0ef8.html b/preview/reference/boost/capy/run_async-0ef8.html new file mode 100644 index 0000000..fbac205 --- /dev/null +++ b/preview/reference/boost/capy/run_async-0ef8.html @@ -0,0 +1,709 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

run_async overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+

Asynchronously launch a lazy task on the given executor.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(Ex ex);
+
+
+ +
+

Asynchronously launch a lazy task with stop token support.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st);
+
+
+ +
+

Asynchronously launch a lazy task with custom memory resource.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::pmr::memory_resource* mr);
+
+
+ +
+

Asynchronously launch a lazy task with a result handler.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    H1 h1);
+
+
+ +
+

Asynchronously launch a lazy task with stop token and memory resource.

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr);
+
+
+ +
+

Asynchronously launch a lazy task with stop token and result handler.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    H1 h1);
+
+
+ +
+

Asynchronously launch a lazy task with memory resource and handler.

+
+
+
+
template<
+    Executor Ex,
+    class H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::pmr::memory_resource* mr,
+    H1 h1);
+
+
+ +
+

Asynchronously launch a lazy task with separate result and error handlers.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    H1 h1,
+    H2 h2);
+
+
+ +
+

Asynchronously launch a lazy task with stop token, memory resource, and handler.

+
+
+
+
template<
+    Executor Ex,
+    class H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr,
+    H1 h1);
+
+
+ +
+

Asynchronously launch a lazy task with stop token and separate handlers.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    H1 h1,
+    H2 h2);
+
+
+ +
+

Asynchronously launch a lazy task with memory resource and handlers.

+
+
+
+
template<
+    Executor Ex,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::pmr::memory_resource* mr,
+    H1 h1,
+    H2 h2);
+
+
+ +
+

Asynchronously launch a lazy task with allocator and handlers.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    Alloc alloc,
+    H1 h1,
+    H2 h2);
+
+
+ +
+

Asynchronously launch a lazy task with stop token, memory resource, and handlers.

+
+
+
+
template<
+    Executor Ex,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr,
+    H1 h1,
+    H2 h2);
+
+
+ +
+

Asynchronously launch a lazy task with stop token, allocator, and handlers.

+
+
+
+
template<
+    Executor Ex,
+    /* implementation-defined */ Alloc,
+    class H1,
+    class H2>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    Alloc alloc,
+    H1 h1,
+    H2 h2);
+
+
+ +
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

h1

The handler to invoke with the result (and optionally exception).

alloc

The allocator for frame allocation (copied and stored).

h2

The handler to invoke with the exception on failure.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-0ef9.html b/preview/reference/boost/capy/run_async-0ef9.html new file mode 100644 index 0000000..9c9155d --- /dev/null +++ b/preview/reference/boost/capy/run_async-0ef9.html @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with memory resource and handler.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    class H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::pmr::memory_resource* mr,
+    H1 h1);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

mr

The memory resource for frame allocation.

h1

The handler to invoke with the result (and optionally exception).

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-0f1.html b/preview/reference/boost/capy/run_async-0f1.html new file mode 100644 index 0000000..25bbaae --- /dev/null +++ b/preview/reference/boost/capy/run_async-0f1.html @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task with stop token, memory resource, and handler.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    class H1>
+[[nodiscard]]
+auto
+run_async(
+    Ex ex,
+    std::stop_token st,
+    std::pmr::memory_resource* mr,
+    H1 h1);
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

st

The stop token for cooperative cancellation.

mr

The memory resource for frame allocation.

h1

The handler to invoke with the result (and optionally exception).

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async-0f7.html b/preview/reference/boost/capy/run_async-0f7.html new file mode 100644 index 0000000..757dd58 --- /dev/null +++ b/preview/reference/boost/capy/run_async-0f7.html @@ -0,0 +1,458 @@ + + + + + + + + + + + + + + boost::capy::run_async :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async

+
+
+
+

Asynchronously launch a lazy task on the given executor.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<Executor Ex>
+[[nodiscard]]
+auto
+run_async(Ex ex);
+
+
+
+
+
+

Description

+
+
+

Use this to start execution of a task<T> that was created lazily. The returned wrapper must be immediately invoked with the task; storing the wrapper and calling it later violates LIFO ordering.

+
+
+

Uses the default recycling frame allocator for coroutine frames. With no handlers, the result is discarded and exceptions are rethrown.

+
+
+
+
+

Thread Safety

+
+
+

The wrapper and handlers may be called from any thread where the executor schedules work.

+
+
+
+
+

Example

+
+
+
+
run_async(ioc.get_executor())(my_task());
+
+
+
+
+
+

Return Value

+
+
+

A wrapper that accepts a task<T> for immediate execution.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The executor to execute the task on.

+
+
+
+

See Also

+
+
+

task

+
+
+

executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper.html b/preview/reference/boost/capy/run_async_wrapper.html new file mode 100644 index 0000000..753e4a2 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper.html @@ -0,0 +1,494 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper

+
+
+
+

Wrapper returned by run_async that accepts a task for execution.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<
+    Executor Ex,
+    class Handlers,
+    class Alloc>
+class run_async_wrapper;
+
+
+
+
+
+

Description

+
+
+

This wrapper holds the run_async_trampoline coroutine, executor, stop token, and handlers. The run_async_trampoline is allocated when the wrapper is constructed (before the task due to C++17 postfix evaluation order).

+
+
+

The rvalue ref‐qualifier on operator() ensures the wrapper can only be used as a temporary, preventing misuse that would violate LIFO ordering.

+
+
+
+
+

Thread Safety

+
+
+

The wrapper itself should only be used from one thread. The handlers may be invoked from any thread where the executor schedules work.

+
+
+
+
+

Example

+
+
+
+
// Correct usage - wrapper is temporary
+run_async(ex)(my_task());
+
+// Compile error - cannot call operator() on lvalue
+auto w = run_async(ex);
+w(my_task());  // Error: operator() requires rvalue
+
+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

run_async_wrapper [constructor] [deleted]

Construct wrapper with executor, stop token, handlers, and allocator.

~run_async_wrapper [destructor]

Destructor

operator= [deleted]

Assignment operators

operator()

Launch the task for execution.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

Ex

The executor type satisfying the Executor concept.

Handlers

The handler type (default_handler or handler_pair).

Alloc

The allocator type (value type or memory_resource*).

+
+
+
+

See Also

+
+
+

run_async

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/2constructor-01.html b/preview/reference/boost/capy/run_async_wrapper/2constructor-01.html new file mode 100644 index 0000000..adad0a9 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/2constructor-01.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::run_async_wrapper :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper::run_async_wrapper

+
+
+
+

Construct wrapper with executor, stop token, handlers, and allocator.

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+

Copy constructor

+
+
+
+
run_async_wrapper(run_async_wrapper const& other) = delete;
+
+
+ +
+

Move constructor

+
+
+
+
run_async_wrapper(run_async_wrapper&& other) = delete;
+
+
+ +
+

Construct wrapper with executor, stop token, handlers, and allocator.

+
+
+
+
run_async_wrapper(
+    Ex ex,
+    std::stop_token st,
+    Handlers h,
+    Alloc a) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/2constructor-0d.html b/preview/reference/boost/capy/run_async_wrapper/2constructor-0d.html new file mode 100644 index 0000000..01b108c --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/2constructor-0d.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::run_async_wrapper :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper::run_async_wrapper

+
+
+
+

Construct wrapper with executor, stop token, handlers, and allocator.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
run_async_wrapper(
+    Ex ex,
+    std::stop_token st,
+    Handlers h,
+    Alloc a) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The object to construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/2constructor-0e6.html b/preview/reference/boost/capy/run_async_wrapper/2constructor-0e6.html new file mode 100644 index 0000000..ee37307 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/2constructor-0e6.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::run_async_wrapper :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/2constructor-0ed.html b/preview/reference/boost/capy/run_async_wrapper/2constructor-0ed.html new file mode 100644 index 0000000..d0b2ef3 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/2constructor-0ed.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::run_async_wrapper :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/2destructor.html b/preview/reference/boost/capy/run_async_wrapper/2destructor.html new file mode 100644 index 0000000..2cff279 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::~run_async_wrapper :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/operator_assign-0a.html b/preview/reference/boost/capy/run_async_wrapper/operator_assign-0a.html new file mode 100644 index 0000000..67162f1 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/operator_assign-0a.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
run_async_wrapper&
+operator=(run_async_wrapper const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/operator_assign-0b.html b/preview/reference/boost/capy/run_async_wrapper/operator_assign-0b.html new file mode 100644 index 0000000..a855b22 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/operator_assign-0b.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper::operator=

+
+
+
+

Assignment operators

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+

Copy assignment operator

+
+
+
+
run_async_wrapper&
+operator=(run_async_wrapper const& other) = delete;
+
+
+ +
+

Move assignment operator

+
+
+ +
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/operator_assign-0e.html b/preview/reference/boost/capy/run_async_wrapper/operator_assign-0e.html new file mode 100644 index 0000000..de8e34d --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/operator_assign-0e.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper::operator=

+
+
+
+

Move assignment operator

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
run_async_wrapper&
+operator=(run_async_wrapper&& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/run_async_wrapper/operator_call.html b/preview/reference/boost/capy/run_async_wrapper/operator_call.html new file mode 100644 index 0000000..c7c7ea2 --- /dev/null +++ b/preview/reference/boost/capy/run_async_wrapper/operator_call.html @@ -0,0 +1,443 @@ + + + + + + + + + + + + + + boost::capy::run_async_wrapper::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::run_async_wrapper::operator()

+
+
+
+

Launch the task for execution.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/run_async.hpp>

+
+
+
+
template<IoRunnable Task>
+void
+operator()(Task t) &&;
+
+
+
+
+
+

Description

+
+
+

This operator accepts a task and launches it on the executor. The rvalue ref‐qualifier ensures the wrapper is consumed, enforcing correct LIFO destruction order.

+
+
+

The io_env constructed for the task is owned by the trampoline coroutine and is guaranteed to outlive the task and all awaitables in its chain. Awaitables may store io_env const* without concern for dangling references.

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Task

The IoRunnable type.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

t

The task to execute. Ownership is transferred to the run_async_trampoline which will destroy it after completion.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/sans_prefix.html b/preview/reference/boost/capy/sans_prefix.html new file mode 100644 index 0000000..af0ec92 --- /dev/null +++ b/preview/reference/boost/capy/sans_prefix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::sans_prefix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/sans_prefix_mrdocs_workaround_t.html b/preview/reference/boost/capy/sans_prefix_mrdocs_workaround_t.html new file mode 100644 index 0000000..87f1974 --- /dev/null +++ b/preview/reference/boost/capy/sans_prefix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::sans_prefix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::sans_prefix_mrdocs_workaround_t

+
+
+
+

Return a sequence representing all but the first n bytes of a buffer sequence

+
+
+
+
+

Synopsis

+
+ +
+
+
struct sans_prefix_mrdocs_workaround_t;
+
+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/sans_prefix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/sans_prefix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..f2ddbdb --- /dev/null +++ b/preview/reference/boost/capy/sans_prefix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::sans_prefix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/sans_suffix.html b/preview/reference/boost/capy/sans_suffix.html new file mode 100644 index 0000000..7b5f33d --- /dev/null +++ b/preview/reference/boost/capy/sans_suffix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::sans_suffix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/sans_suffix_mrdocs_workaround_t.html b/preview/reference/boost/capy/sans_suffix_mrdocs_workaround_t.html new file mode 100644 index 0000000..1d4a202 --- /dev/null +++ b/preview/reference/boost/capy/sans_suffix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::sans_suffix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::sans_suffix_mrdocs_workaround_t

+
+
+
+

Return a sequence representing all but the last n bytes of a buffer sequence

+
+
+
+
+

Synopsis

+
+ +
+
+
struct sans_suffix_mrdocs_workaround_t;
+
+
+
+
+
+

Member Functions

+
+ +++ + + + + + + + + +

Name

operator()

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/sans_suffix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/sans_suffix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..f48041b --- /dev/null +++ b/preview/reference/boost/capy/sans_suffix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::sans_suffix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/set_current_frame_allocator.html b/preview/reference/boost/capy/set_current_frame_allocator.html new file mode 100644 index 0000000..b068038 --- /dev/null +++ b/preview/reference/boost/capy/set_current_frame_allocator.html @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + boost::capy::set_current_frame_allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::set_current_frame_allocator

+
+
+
+

Set the current frame allocator for this thread.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+set_current_frame_allocator(std::pmr::memory_resource* mr) noexcept;
+
+
+
+
+
+

Description

+
+
+

Installs mr as the frame allocator that will be read by the next coroutine's promise_type::operator new on this thread. Only launch functions and IoAwaitable machinery should call this; see get_current_frame_allocator for the full protocol description.

+
+
+

Passing nullptr means "not specified" ‐ no particular allocator is established for the chain.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

mr

The memory_resource to install, or nullptr to clear.

+
+
+
+

See Also

+
+
+

get_current_frame_allocator, IoAwaitable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/size_tag.html b/preview/reference/boost/capy/size_tag.html new file mode 100644 index 0000000..fd961b5 --- /dev/null +++ b/preview/reference/boost/capy/size_tag.html @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + boost::capy::size_tag :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::size_tag

+
+
+
+

Tag type for customizing buffer_size via tag_invoke.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
struct size_tag;
+
+
+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

tag_invoke

Return the total byte count in O(1).

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_how.html b/preview/reference/boost/capy/slice_how.html new file mode 100644 index 0000000..885c9f6 --- /dev/null +++ b/preview/reference/boost/capy/slice_how.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + boost::capy::slice_how :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_how

+
+
+
+

Constants for slice customization.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
enum class slice_how : int;
+
+
+
+
+
+

Description

+
+
+

Passed to tag_invoke overloads to specify which portion of a buffer sequence to retain.

+
+
+
+
+

Members

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

remove_prefix

Remove bytes from the front of the sequence.

keep_prefix

Keep only the first N bytes.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07.html b/preview/reference/boost/capy/slice_of-07.html new file mode 100644 index 0000000..ad9bec1 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07.html @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_of<BufferSequence>

+
+
+
+

A wrapper enabling a buffer sequence to be consumed

+
+
+
+
+

Synopsis

+
+ +
+
+
template<ConstBufferSequence BufferSequence>
+class slice_of<BufferSequence>;
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

const_iterator

The type of returned iterators

value_type

The type of values returned by iterators

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

slice_of [constructor]

Constructor

begin

Return an iterator to the beginning of the sequence

end

Return an iterator to the end of the sequence

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::tag_invoke

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/2constructor-01.html b/preview/reference/boost/capy/slice_of-07/2constructor-01.html new file mode 100644 index 0000000..e39ec3f --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/2constructor-01.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::slice_of :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/2constructor-04.html b/preview/reference/boost/capy/slice_of-07/2constructor-04.html new file mode 100644 index 0000000..833d45f --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/2constructor-04.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::slice_of :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/2constructor-0d.html b/preview/reference/boost/capy/slice_of-07/2constructor-0d.html new file mode 100644 index 0000000..ec04705 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/2constructor-0d.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::slice_of :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/begin.html b/preview/reference/boost/capy/slice_of-07/begin.html new file mode 100644 index 0000000..84f88b3 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/begin.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::begin :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator.html b/preview/reference/boost/capy/slice_of-07/const_iterator.html new file mode 100644 index 0000000..67845a3 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator.html @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_of<BufferSequence>::const_iterator

+
+
+
+

The type of returned iterators

+
+
+
+
+

Synopsis

+
+ +
+
+
class const_iterator;
+
+
+
+
+
+

Types

+
+ +++ + + + + + + + + + + + + + + + + + + + + + + + +

Name

difference_type

iterator_category

iterator_concept

pointer

reference

value_type

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

const_iterator [constructor]

Default constructor

operator*

operator++

Increment operators

operator‐‐

Decrement operators

operator==

Equality operator

operator!=

Inequality operator

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::slice_of<BufferSequence>

A wrapper enabling a buffer sequence to be consumed

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/2constructor.html b/preview/reference/boost/capy/slice_of-07/const_iterator/2constructor.html new file mode 100644 index 0000000..6c87548 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/2constructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::const_iterator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/difference_type.html b/preview/reference/boost/capy/slice_of-07/const_iterator/difference_type.html new file mode 100644 index 0000000..77588fc --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/difference_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::difference_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/iterator_category.html b/preview/reference/boost/capy/slice_of-07/const_iterator/iterator_category.html new file mode 100644 index 0000000..45b2c19 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/iterator_category.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::iterator_category :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/iterator_concept.html b/preview/reference/boost/capy/slice_of-07/const_iterator/iterator_concept.html new file mode 100644 index 0000000..86aa617 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/iterator_concept.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::iterator_concept :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-05c.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-05c.html new file mode 100644 index 0000000..ca13016 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-05c.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator‐‐ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_of<BufferSequence>::const_iterator::operator‐‐

+
+
+
+

Decrement operators

+
+
+
+
+

Synopses

+
+ +
+

Decrement operator

+
+
+
+
const_iterator&
+operator‐‐() noexcept;
+
+
+ +
+

Decrement operator

+
+
+
+
const_iterator
+operator‐‐(int) noexcept;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-05f.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-05f.html new file mode 100644 index 0000000..261a237 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-05f.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator‐‐ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-0a.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-0a.html new file mode 100644 index 0000000..89fddc7 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_dec-0a.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator‐‐ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_eq.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_eq.html new file mode 100644 index 0000000..b4a47ae --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator== :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_of<BufferSequence>::const_iterator::operator==

+
+
+
+

Equality operator

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator==(const_iterator const& other) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

true if the objects are equal, false otherwise

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-00.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-00.html new file mode 100644 index 0000000..19aae16 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-00.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator++ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-02.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-02.html new file mode 100644 index 0000000..df7b773 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-02.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator++ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-03.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-03.html new file mode 100644 index 0000000..f71e0a9 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_inc-03.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator++ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_not_eq.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_not_eq.html new file mode 100644 index 0000000..b95f452 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_not_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator!= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_of<BufferSequence>::const_iterator::operator!=

+
+
+
+

Inequality operator

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator!=(const_iterator const& other) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

true if the objects are not equal, false otherwise

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/operator_star.html b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_star.html new file mode 100644 index 0000000..f66cb96 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/operator_star.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::operator* :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/pointer.html b/preview/reference/boost/capy/slice_of-07/const_iterator/pointer.html new file mode 100644 index 0000000..c6b7ff8 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/pointer.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::pointer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/reference.html b/preview/reference/boost/capy/slice_of-07/const_iterator/reference.html new file mode 100644 index 0000000..8a9c36f --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/reference.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::reference :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/const_iterator/value_type.html b/preview/reference/boost/capy/slice_of-07/const_iterator/value_type.html new file mode 100644 index 0000000..b82136e --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/const_iterator/value_type.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::const_iterator::value_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/end.html b/preview/reference/boost/capy/slice_of-07/end.html new file mode 100644 index 0000000..b929392 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/end.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::end :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-07/value_type.html b/preview/reference/boost/capy/slice_of-07/value_type.html new file mode 100644 index 0000000..1c81049 --- /dev/null +++ b/preview/reference/boost/capy/slice_of-07/value_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::slice_of<BufferSequence>::value_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_of-0a.html b/preview/reference/boost/capy/slice_of-0a.html new file mode 100644 index 0000000..5d1805f --- /dev/null +++ b/preview/reference/boost/capy/slice_of-0a.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::slice_of :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/slice_tag.html b/preview/reference/boost/capy/slice_tag.html new file mode 100644 index 0000000..5ea29bf --- /dev/null +++ b/preview/reference/boost/capy/slice_tag.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::slice_tag :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::slice_tag

+
+
+
+

Tag type for customizing slice operations via tag_invoke.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
struct slice_tag;
+
+
+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

tag_invoke

Slice customization point.

tag_invoke

Slice customization point for tag_invoke.

tag_invoke

Slice customization point for tag_invoke.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/slice_type.html b/preview/reference/boost/capy/slice_type.html new file mode 100644 index 0000000..07f7120 --- /dev/null +++ b/preview/reference/boost/capy/slice_type.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::slice_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02.html b/preview/reference/boost/capy/strand-02.html new file mode 100644 index 0000000..ec9e955 --- /dev/null +++ b/preview/reference/boost/capy/strand-02.html @@ -0,0 +1,553 @@ + + + + + + + + + + + + + + boost::capy::strand :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand

+
+
+
+

Provides serialized coroutine execution for any executor type.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
template<typename Executor>
+class strand;
+
+
+
+
+
+

Description

+
+
+

A strand wraps an inner executor and ensures that coroutines dispatched through it never run concurrently. At most one coroutine executes at a time within a strand, even when the underlying executor runs on multiple threads.

+
+
+

Strands are lightweight handles that can be copied freely. Copies share the same internal serialization state, so coroutines dispatched through any copy are serialized with respect to all other copies.

+
+
+
+
+

Invariant

+
+
+

Coroutines resumed through a strand shall not run concurrently.

+
+
+
+
+

Implementation

+
+
+

The strand uses a service‐based architecture with a fixed pool of 211 implementation objects. New strands hash to select an impl from the pool. Strands that hash to the same index share serialization, which is harmless (just extra serialization) and rare with 211 buckets.

+
+
+
+
+

Executor Concept

+
+
+

This class satisfies the Executor concept, providing: ‐ context() ‐ Returns the underlying execution context ‐ on_work_started() / on_work_finished() ‐ Work tracking ‐ dispatch(h) ‐ May run immediately if strand is idle ‐ post(h) ‐ Always queues for later execution

+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Safe.

+
+
+
+
+

Example

+
+
+
+
thread_pool pool(4);
+auto strand = make_strand(pool.get_executor());
+
+// These coroutines will never run concurrently
+strand.post(coro1);
+strand.post(coro2);
+strand.post(coro3);
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

inner_executor_type

The type of the underlying executor.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

strand [constructor]

Constructors

operator=

Assignment operators

context

Return the underlying execution context.

dispatch

Dispatch a coroutine through the strand.

get_inner_executor

Return the underlying executor.

on_work_finished

Notify that work has finished.

on_work_started

Notify that work has started.

post

Post a coroutine to the strand.

running_in_this_thread

Determine whether the strand is running in the current thread.

operator==

Compare two strands for equality.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

E

The type of the underlying executor. Must satisfy the Executor concept.

+
+
+
+

See Also

+
+
+

make_strand, Executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/2constructor-01.html b/preview/reference/boost/capy/strand-02/2constructor-01.html new file mode 100644 index 0000000..d9f100d --- /dev/null +++ b/preview/reference/boost/capy/strand-02/2constructor-01.html @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + boost::capy::strand::strand :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::strand

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+

Copy constructor.

+
+
+
+
strand(strand const& other) = default;
+
+
+ +
+

Move constructor.

+
+
+
+
strand(strand&& other) = default;
+
+
+ +
+

Construct a strand for the specified executor.

+
+
+
+
template<typename Ex1>
+requires !std::is_same_v<std::decay_t<Ex1>, strand> &&
+            !detail::is_strand<std::decay_t<Ex1>>::value &&
+            std::is_convertible_v<Ex1, Ex>
+explicit
+strand(Ex1&& ex);
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The inner executor to wrap. Coroutines will ultimately be dispatched through this executor.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/2constructor-04.html b/preview/reference/boost/capy/strand-02/2constructor-04.html new file mode 100644 index 0000000..9b62bdb --- /dev/null +++ b/preview/reference/boost/capy/strand-02/2constructor-04.html @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + boost::capy::strand::strand :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::strand

+
+
+
+

Construct a strand for the specified executor.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
template<typename Ex1>
+requires !std::is_same_v<std::decay_t<Ex1>, strand> &&
+            !detail::is_strand<std::decay_t<Ex1>>::value &&
+            std::is_convertible_v<Ex1, Ex>
+explicit
+strand(Ex1&& ex);
+
+
+
+
+
+

Description

+
+
+

Obtains a strand implementation from the service associated with the executor's context. The implementation is selected from a fixed pool using a hash function.

+
+
+ + + + + +
+ + +
+

This constructor is disabled if the argument is a strand type, to prevent strand‐of‐strand wrapping.

+
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The inner executor to wrap. Coroutines will ultimately be dispatched through this executor.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/2constructor-0c.html b/preview/reference/boost/capy/strand-02/2constructor-0c.html new file mode 100644 index 0000000..377c610 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/2constructor-0c.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + boost::capy::strand::strand :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::strand

+
+
+
+

Copy constructor.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
strand(strand const& other) = default;
+
+
+
+
+
+

Description

+
+
+

Creates a strand that shares serialization state with the original. Coroutines dispatched through either strand will be serialized with respect to each other.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy construct from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/2constructor-0f.html b/preview/reference/boost/capy/strand-02/2constructor-0f.html new file mode 100644 index 0000000..6ac4883 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/2constructor-0f.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::strand::strand :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/context.html b/preview/reference/boost/capy/strand-02/context.html new file mode 100644 index 0000000..167fb7f --- /dev/null +++ b/preview/reference/boost/capy/strand-02/context.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::strand::context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/dispatch.html b/preview/reference/boost/capy/strand-02/dispatch.html new file mode 100644 index 0000000..dbcdd35 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/dispatch.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::strand::dispatch :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::dispatch

+
+
+
+

Dispatch a coroutine through the strand.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
std::coroutine_handle
+dispatch(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

Returns a handle for symmetric transfer. If the calling thread is already executing within this strand, returns h. Otherwise, the coroutine is queued and std::noop_coroutine() is returned.

+
+
+
+
+

Ordering

+
+
+

Callers requiring strict FIFO ordering should use post() instead, which always queues the coroutine.

+
+
+
+
+

Return Value

+
+
+

A handle for symmetric transfer or std::noop_coroutine().

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to dispatch.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/get_inner_executor.html b/preview/reference/boost/capy/strand-02/get_inner_executor.html new file mode 100644 index 0000000..84cf161 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/get_inner_executor.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::strand::get_inner_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/inner_executor_type.html b/preview/reference/boost/capy/strand-02/inner_executor_type.html new file mode 100644 index 0000000..d7aec61 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/inner_executor_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::strand::inner_executor_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/on_work_finished.html b/preview/reference/boost/capy/strand-02/on_work_finished.html new file mode 100644 index 0000000..6c02048 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/on_work_finished.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::strand::on_work_finished :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::on_work_finished

+
+
+
+

Notify that work has finished.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
void
+on_work_finished() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Delegates to the inner executor's on_work_finished(). This is a no‐op for most executor types.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/on_work_started.html b/preview/reference/boost/capy/strand-02/on_work_started.html new file mode 100644 index 0000000..ecbbfef --- /dev/null +++ b/preview/reference/boost/capy/strand-02/on_work_started.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::strand::on_work_started :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::on_work_started

+
+
+
+

Notify that work has started.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
void
+on_work_started() const noexcept;
+
+
+
+
+
+

Description

+
+
+

Delegates to the inner executor's on_work_started(). This is a no‐op for most executor types.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/operator_assign-04.html b/preview/reference/boost/capy/strand-02/operator_assign-04.html new file mode 100644 index 0000000..aca7e95 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/operator_assign-04.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::strand::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/operator_assign-0d.html b/preview/reference/boost/capy/strand-02/operator_assign-0d.html new file mode 100644 index 0000000..b030692 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/operator_assign-0d.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::strand::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/operator_assign-0f.html b/preview/reference/boost/capy/strand-02/operator_assign-0f.html new file mode 100644 index 0000000..087d0c0 --- /dev/null +++ b/preview/reference/boost/capy/strand-02/operator_assign-0f.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::strand::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/operator_eq.html b/preview/reference/boost/capy/strand-02/operator_eq.html new file mode 100644 index 0000000..1ee8a6d --- /dev/null +++ b/preview/reference/boost/capy/strand-02/operator_eq.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::strand::operator== :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::operator==

+
+
+
+

Compare two strands for equality.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
bool
+operator==(strand const& other) const noexcept;
+
+
+
+
+
+

Description

+
+
+

Two strands are equal if they share the same internal serialization state. Equal strands serialize coroutines with respect to each other.

+
+
+
+
+

Return Value

+
+
+

true if both strands share the same implementation.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The strand to compare against.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/post.html b/preview/reference/boost/capy/strand-02/post.html new file mode 100644 index 0000000..d2162ee --- /dev/null +++ b/preview/reference/boost/capy/strand-02/post.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::strand::post :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::post

+
+
+
+

Post a coroutine to the strand.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
void
+post(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

The coroutine is always queued for execution, never resumed immediately. When the strand becomes available, queued coroutines execute in FIFO order on the underlying executor.

+
+
+
+
+

Ordering

+
+
+

Guarantees strict FIFO ordering relative to other post() calls. Use this instead of dispatch() when ordering matters.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to post.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-02/running_in_this_thread.html b/preview/reference/boost/capy/strand-02/running_in_this_thread.html new file mode 100644 index 0000000..c91ab7d --- /dev/null +++ b/preview/reference/boost/capy/strand-02/running_in_this_thread.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::strand::running_in_this_thread :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::strand::running_in_this_thread

+
+
+
+

Determine whether the strand is running in the current thread.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/strand.hpp>

+
+
+
+
bool
+running_in_this_thread() const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

true if the current thread is executing a coroutine within this strand's dispatch loop.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/strand-05.html b/preview/reference/boost/capy/strand-05.html new file mode 100644 index 0000000..194defe --- /dev/null +++ b/preview/reference/boost/capy/strand-05.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::strand<Ex> :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/string_dynamic_buffer.html b/preview/reference/boost/capy/string_dynamic_buffer.html new file mode 100644 index 0000000..c9a1eab --- /dev/null +++ b/preview/reference/boost/capy/string_dynamic_buffer.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::string_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/suffix.html b/preview/reference/boost/capy/suffix.html new file mode 100644 index 0000000..351bf0e --- /dev/null +++ b/preview/reference/boost/capy/suffix.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::suffix :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/suffix_mrdocs_workaround_t.html b/preview/reference/boost/capy/suffix_mrdocs_workaround_t.html new file mode 100644 index 0000000..21b6017 --- /dev/null +++ b/preview/reference/boost/capy/suffix_mrdocs_workaround_t.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + boost::capy::suffix_mrdocs_workaround_t :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/suffix_mrdocs_workaround_t/operator_call.html b/preview/reference/boost/capy/suffix_mrdocs_workaround_t/operator_call.html new file mode 100644 index 0000000..0380804 --- /dev/null +++ b/preview/reference/boost/capy/suffix_mrdocs_workaround_t/operator_call.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::suffix_mrdocs_workaround_t::operator() :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-00.html b/preview/reference/boost/capy/tag_invoke-00.html new file mode 100644 index 0000000..7dbbd50 --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-00.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-02.html b/preview/reference/boost/capy/tag_invoke-02.html new file mode 100644 index 0000000..26a57ca --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-02.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-07.html b/preview/reference/boost/capy/tag_invoke-07.html new file mode 100644 index 0000000..ef1c058 --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-07.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::tag_invoke

+
+
+
+

Slice customization point.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+tag_invoke(
+    slice_tag const&,
+    buffer_array& ba,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

ba

A buffer sequence holding up to N buffers.

how

Constants for slice customization.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-088.html b/preview/reference/boost/capy/tag_invoke-088.html new file mode 100644 index 0000000..fe7766c --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-088.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-08b.html b/preview/reference/boost/capy/tag_invoke-08b.html new file mode 100644 index 0000000..adeb20f --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-08b.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-0a.html b/preview/reference/boost/capy/tag_invoke-0a.html new file mode 100644 index 0000000..e234f51 --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-0a.html @@ -0,0 +1,492 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::tag_invoke

+
+
+
+

tag_invoke overloads

+
+
+
+
+

Synopses

+
+ +
+

Return the total byte count in O(1).

+
+
+
+
std::size_t
+tag_invoke(
+    size_tag const&,
+    buffer_array const& ba) noexcept;
+
+
+ +
+
+
template<ConstBufferSequence CB>
+std::size_t
+tag_invoke(
+    size_tag const&,
+    CB const& bs) noexcept;
+
+
+ +
+

Slice customization point.

+
+
+
+
void
+tag_invoke(
+    slice_tag const&,
+    buffer_array& ba,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+ +
+

Slice customization point for tag_invoke.

+
+
+
+
void
+tag_invoke(
+    slice_tag const&,
+    const_buffer& b,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+ +
+
+
void
+tag_invoke(
+    slice_tag const&,
+    const_buffer_pair& bs,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+ +
+

Slice customization point for tag_invoke.

+
+
+
+
void
+tag_invoke(
+    slice_tag const&,
+    mutable_buffer& b,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+ +
+
+
void
+tag_invoke(
+    slice_tag const&,
+    mutable_buffer_pair& bs,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+ +
+
+
void
+tag_invoke(
+    slice_tag const&,
+    slice_of<BufferSequence>& bs,
+    slice_how how,
+    std::size_t n);
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-0b.html b/preview/reference/boost/capy/tag_invoke-0b.html new file mode 100644 index 0000000..570f7c1 --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-0b.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::tag_invoke

+
+
+
+

Return the total byte count in O(1).

+
+
+
+
+

Synopsis

+
+ +
+
+
std::size_t
+tag_invoke(
+    size_tag const&,
+    buffer_array const& ba) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

the total byte count in O(1).

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ba

A buffer sequence holding up to N buffers.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-0c.html b/preview/reference/boost/capy/tag_invoke-0c.html new file mode 100644 index 0000000..3d41580 --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-0c.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::tag_invoke

+
+
+
+

Slice customization point for tag_invoke.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
void
+tag_invoke(
+    slice_tag const&,
+    const_buffer& b,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

b

A reference to a contiguous region of read‐only memory.

how

Constants for slice customization.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/tag_invoke-0e.html b/preview/reference/boost/capy/tag_invoke-0e.html new file mode 100644 index 0000000..e1267a3 --- /dev/null +++ b/preview/reference/boost/capy/tag_invoke-0e.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::tag_invoke :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::tag_invoke

+
+
+
+

Slice customization point for tag_invoke.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/buffers.hpp>

+
+
+
+
void
+tag_invoke(
+    slice_tag const&,
+    mutable_buffer& b,
+    slice_how how,
+    std::size_t n) noexcept;
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

b

A reference to a contiguous region of writable memory.

how

Constants for slice customization.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task.html b/preview/reference/boost/capy/task.html new file mode 100644 index 0000000..96aead9 --- /dev/null +++ b/preview/reference/boost/capy/task.html @@ -0,0 +1,575 @@ + + + + + + + + + + + + + + boost::capy::task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task

+
+
+
+

Lazy coroutine task satisfying IoRunnable.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
template<typename T = void>
+struct task;
+
+
+
+
+
+

Description

+
+
+

Use task<T> as the return type for coroutines that perform I/O and return a value of type T. The coroutine body does not start executing until the task is awaited, enabling efficient composition without unnecessary eager execution.

+
+
+

The task participates in the I/O awaitable protocol: when awaited, it receives the caller's executor and stop token, propagating them to nested co_await expressions. This enables cancellation and proper completion dispatch across executor boundaries.

+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Unsafe.

+
+
+
+
+

Example

+
+
+
+
task<int> compute_value()
+{
+    auto [ec, n] = co_await stream.read_some( buf );
+    if( ec )
+        co_return 0;
+    co_return process( buf, n );
+}
+
+task<> run_session( tcp_socket sock )
+{
+    int result = co_await compute_value();
+    // ...
+}
+
+
+
+
+
+

Types

+
+ +++ + + + + + + + + +

Name

promise_type

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

task [constructor] [deleted]

Move construct, transferring ownership.

~task [destructor]

Destroy the task and its coroutine frame if owned.

operator= [deleted]

Move assign, transferring ownership.

await_ready

Return false; tasks are never immediately ready.

await_resume

Return the result or rethrow any stored exception.

await_suspend

Start execution with the caller's context.

handle

Return the coroutine handle.

release

Release ownership of the coroutine frame.

+
+
+
+

Data Members

+
+ +++ + + + + + + + + +

Name

h_

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

when_all

Execute multiple awaitables concurrently and collect their results.

when_any

Wait for the first awaitable to complete (void range overload).

when_any

Wait for the first awaitable to complete.

when_any

Wait for the first awaitable to complete (range overload).

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

T

The result type. Use task<> for task<void>.

+
+
+
+

See Also

+
+
+

IoRunnable, IoAwaitable, run, run_async

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task/2constructor-00.html b/preview/reference/boost/capy/task/2constructor-00.html new file mode 100644 index 0000000..9ed5207 --- /dev/null +++ b/preview/reference/boost/capy/task/2constructor-00.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::task::task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/2constructor-03.html b/preview/reference/boost/capy/task/2constructor-03.html new file mode 100644 index 0000000..b98da23 --- /dev/null +++ b/preview/reference/boost/capy/task/2constructor-03.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::task::task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/2constructor-0b.html b/preview/reference/boost/capy/task/2constructor-0b.html new file mode 100644 index 0000000..694efb6 --- /dev/null +++ b/preview/reference/boost/capy/task/2constructor-0b.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::task::task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/2destructor.html b/preview/reference/boost/capy/task/2destructor.html new file mode 100644 index 0000000..0b69672 --- /dev/null +++ b/preview/reference/boost/capy/task/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::task::~task :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/await_ready.html b/preview/reference/boost/capy/task/await_ready.html new file mode 100644 index 0000000..ae22a8f --- /dev/null +++ b/preview/reference/boost/capy/task/await_ready.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::task::await_ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task::await_ready

+
+
+
+

Return false; tasks are never immediately ready.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
bool
+await_ready() const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

false; tasks are never immediately ready.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task/await_resume.html b/preview/reference/boost/capy/task/await_resume.html new file mode 100644 index 0000000..329c64a --- /dev/null +++ b/preview/reference/boost/capy/task/await_resume.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::task::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/await_suspend.html b/preview/reference/boost/capy/task/await_suspend.html new file mode 100644 index 0000000..6cb54eb --- /dev/null +++ b/preview/reference/boost/capy/task/await_suspend.html @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + boost::capy::task::await_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task::await_suspend

+
+
+
+

Start execution with the caller's context.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
std::coroutine_handle
+await_suspend(
+    std::coroutine_handle cont,
+    io_env const* env);
+
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

env

Execution environment for IoAwaitables.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task/h_.html b/preview/reference/boost/capy/task/h_.html new file mode 100644 index 0000000..2ecd6a9 --- /dev/null +++ b/preview/reference/boost/capy/task/h_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::task::h_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/handle.html b/preview/reference/boost/capy/task/handle.html new file mode 100644 index 0000000..abf12fd --- /dev/null +++ b/preview/reference/boost/capy/task/handle.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::task::handle :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/operator_assign-02.html b/preview/reference/boost/capy/task/operator_assign-02.html new file mode 100644 index 0000000..7a70d5b --- /dev/null +++ b/preview/reference/boost/capy/task/operator_assign-02.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::task::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/operator_assign-06.html b/preview/reference/boost/capy/task/operator_assign-06.html new file mode 100644 index 0000000..c9ffcf7 --- /dev/null +++ b/preview/reference/boost/capy/task/operator_assign-06.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::task::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task::operator=

+
+
+
+

Move assign, transferring ownership.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
task&
+operator=(task&& other) noexcept;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to move assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task/operator_assign-08.html b/preview/reference/boost/capy/task/operator_assign-08.html new file mode 100644 index 0000000..26aa391 --- /dev/null +++ b/preview/reference/boost/capy/task/operator_assign-08.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::task::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task::operator=

+
+
+
+

Copy assignment operator

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
task&
+operator=(task const& other) = delete;
+
+
+
+
+
+

Return Value

+
+
+

Reference to the current object

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The object to copy assign from

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type.html b/preview/reference/boost/capy/task/promise_type.html new file mode 100644 index 0000000..bb1c61d --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type.html @@ -0,0 +1,514 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task::promise_type

+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
struct promise_type
+    : io_awaitable_promise_base<promise_type>
+    , /* implementation-defined */
+
+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

io_awaitable_promise_base<promise_type>

CRTP mixin that adds I/O awaitable support to a promise type.

/* implementation-defined */

+
+
+
+

Types

+
+ +++ + + + + + + + + +

Name

transform_awaiter

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

promise_type [constructor]

Default constructor

~promise_type [destructor]

Destructor

exception

final_suspend

get_return_object

initial_suspend

transform_awaitable

unhandled_exception

+
+
+
+

Data Members

+
+ +++ + + + + + + + + +

Name

ep_ [variant member]

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::task

Lazy coroutine task satisfying IoRunnable.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/2constructor.html b/preview/reference/boost/capy/task/promise_type/2constructor.html new file mode 100644 index 0000000..d864f93 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/2constructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::promise_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/2destructor.html b/preview/reference/boost/capy/task/promise_type/2destructor.html new file mode 100644 index 0000000..ecd294d --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/2destructor.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::~promise_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/ep_.html b/preview/reference/boost/capy/task/promise_type/ep_.html new file mode 100644 index 0000000..c3bba8c --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/ep_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::ep_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/exception.html b/preview/reference/boost/capy/task/promise_type/exception.html new file mode 100644 index 0000000..77bbf95 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/exception.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::exception :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/final_suspend.html b/preview/reference/boost/capy/task/promise_type/final_suspend.html new file mode 100644 index 0000000..70b1433 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/final_suspend.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::final_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/get_return_object.html b/preview/reference/boost/capy/task/promise_type/get_return_object.html new file mode 100644 index 0000000..b7d3b33 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/get_return_object.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::get_return_object :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/initial_suspend.html b/preview/reference/boost/capy/task/promise_type/initial_suspend.html new file mode 100644 index 0000000..a824863 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/initial_suspend.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::initial_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaitable.html b/preview/reference/boost/capy/task/promise_type/transform_awaitable.html new file mode 100644 index 0000000..4a4dbd7 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaitable.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaitable :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaiter.html b/preview/reference/boost/capy/task/promise_type/transform_awaiter.html new file mode 100644 index 0000000..b3934dd --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaiter.html @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaiter :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaiter/a_.html b/preview/reference/boost/capy/task/promise_type/transform_awaiter/a_.html new file mode 100644 index 0000000..156e790 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaiter/a_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaiter::a_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_ready.html b/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_ready.html new file mode 100644 index 0000000..91e3cab --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_ready.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaiter::await_ready :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_resume.html b/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_resume.html new file mode 100644 index 0000000..51a284c --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_resume.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaiter::await_resume :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_suspend.html b/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_suspend.html new file mode 100644 index 0000000..30e83db --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaiter/await_suspend.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaiter::await_suspend :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/transform_awaiter/p_.html b/preview/reference/boost/capy/task/promise_type/transform_awaiter/p_.html new file mode 100644 index 0000000..9e54744 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/transform_awaiter/p_.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::transform_awaiter::p_ :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/promise_type/unhandled_exception.html b/preview/reference/boost/capy/task/promise_type/unhandled_exception.html new file mode 100644 index 0000000..e3f1e05 --- /dev/null +++ b/preview/reference/boost/capy/task/promise_type/unhandled_exception.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + boost::capy::task::promise_type::unhandled_exception :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/task/release.html b/preview/reference/boost/capy/task/release.html new file mode 100644 index 0000000..f3d9ca3 --- /dev/null +++ b/preview/reference/boost/capy/task/release.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::task::release :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::task::release

+
+
+
+

Release ownership of the coroutine frame.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/task.hpp>

+
+
+
+
void
+release() noexcept;
+
+
+
+
+
+

Description

+
+
+

After calling this, destroying the task does not destroy the coroutine frame. The caller becomes responsible for the frame's lifetime.

+
+
+
+
+

Postconditions

+
+
+

handle() returns the original handle, but the task no longer owns it.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro.html b/preview/reference/boost/capy/this_coro.html new file mode 100644 index 0000000..63b4d59 --- /dev/null +++ b/preview/reference/boost/capy/this_coro.html @@ -0,0 +1,469 @@ + + + + + + + + + + + + + + boost::capy::this_coro :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro

+
+
+
+

Namespace for coroutine environment accessors.

+
+
+
+
+

Description

+
+
+

The this_coro namespace contains tag objects that can be awaited to retrieve information about the current coroutine's execution context. These tags are intercepted by a promise type's await_transform to yield the appropriate values without suspending.

+
+
+
+
+

Example

+
+
+
+
task<void> example()
+{
+    auto const& env = co_await this_coro::environment;
+    auto ex = co_await this_coro::executor;
+    auto token = co_await this_coro::stop_token;
+    auto* alloc = co_await this_coro::allocator;
+}
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

allocator_tag

Tag type for coroutine allocator retrieval.

environment_tag

Tag type for coroutine environment retrieval.

executor_tag

Tag type for coroutine executor retrieval.

stop_token_tag

Tag type for coroutine stop token retrieval.

+
+
+
+

Variables

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

allocator

Tag object that yields the current frame allocator when awaited.

environment

Tag object that yields the current environment when awaited.

executor

Tag object that yields the current executor when awaited.

stop_token

Tag object that yields the current stop token when awaited.

+
+
+
+

See Also

+
+
+

io_awaitable_promise_base, io_env

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/allocator.html b/preview/reference/boost/capy/this_coro/allocator.html new file mode 100644 index 0000000..6e97b4e --- /dev/null +++ b/preview/reference/boost/capy/this_coro/allocator.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + boost::capy::this_coro::allocator :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::allocator

+
+
+
+

Tag object that yields the current frame allocator when awaited.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
inline constexpr allocator_tag allocator = {};
+
+
+
+
+
+

Description

+
+
+

Use co_await this_coro::allocator inside a coroutine whose promise type supports allocator access (e.g., inherits from io_awaitable_promise_base). The returned pointer is the memory resource used for coroutine frame allocation.

+
+
+
+
+

Example

+
+
+
+
task<void> example()
+{
+    auto* alloc = co_await this_coro::allocator;
+    // alloc is nullptr when using the default allocator
+}
+
+
+
+
+
+

Behavior

+
+
+
    +
  • +

    Returns `nullptr` when the default allocator is in use.

    +
  • +
  • +

    This operation never suspends; `await_ready()` always returns `true`.

    +
  • +
+
+
+
+
+

See Also

+
+
+

allocator_tag

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/allocator_tag.html b/preview/reference/boost/capy/this_coro/allocator_tag.html new file mode 100644 index 0000000..c2a586a --- /dev/null +++ b/preview/reference/boost/capy/this_coro/allocator_tag.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::this_coro::allocator_tag :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::allocator_tag

+
+
+
+

Tag type for coroutine allocator retrieval.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
struct allocator_tag;
+
+
+
+
+
+

Description

+
+
+

This tag is intercepted by a promise type's await_transform to yield the coroutine's current frame allocator. The tag itself carries no data; it serves only as a sentinel for compile‐time dispatch.

+
+
+
+
+

See Also

+
+
+

allocator

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/environment.html b/preview/reference/boost/capy/this_coro/environment.html new file mode 100644 index 0000000..092699f --- /dev/null +++ b/preview/reference/boost/capy/this_coro/environment.html @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + boost::capy::this_coro::environment :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::environment

+
+
+
+

Tag object that yields the current environment when awaited.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
inline constexpr environment_tag environment = {};
+
+
+
+
+
+

Description

+
+
+

Use co_await this_coro::environment inside a coroutine whose promise type supports environment access (e.g., inherits from io_awaitable_promise_base). The returned environment contains the executor, stop token, and allocator for this coroutine.

+
+
+
+
+

Example

+
+
+
+
task<void> example()
+{
+    auto const& env = co_await this_coro::environment;
+    // env.executor - the executor this coroutine is bound to
+    // env.stop_token - the stop token for cancellation
+    // env.allocator - the allocator for frame allocation
+}
+
+
+
+
+
+

Behavior

+
+
+
    +
  • +

    Returns a const reference to the stored `io_env`

    +
  • +
  • +

    This operation never suspends; `await_ready()` always returns `true`

    +
  • +
+
+
+
+
+

See Also

+
+
+

environment_tag

+
+
+

io_awaitable_promise_base

+
+
+

io_env

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/environment_tag.html b/preview/reference/boost/capy/this_coro/environment_tag.html new file mode 100644 index 0000000..41f222d --- /dev/null +++ b/preview/reference/boost/capy/this_coro/environment_tag.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::this_coro::environment_tag :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::environment_tag

+
+
+
+

Tag type for coroutine environment retrieval.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
struct environment_tag;
+
+
+
+
+
+

Description

+
+
+

This tag is intercepted by a promise type's await_transform to yield the coroutine's current execution environment. The tag itself carries no data; it serves only as a sentinel for compile‐time dispatch.

+
+
+
+
+

See Also

+
+
+

environment

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/executor.html b/preview/reference/boost/capy/this_coro/executor.html new file mode 100644 index 0000000..9c697a8 --- /dev/null +++ b/preview/reference/boost/capy/this_coro/executor.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::this_coro::executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::executor

+
+
+
+

Tag object that yields the current executor when awaited.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
inline constexpr executor_tag executor = {};
+
+
+
+
+
+

Description

+
+
+

Use co_await this_coro::executor inside a coroutine whose promise type supports executor access (e.g., inherits from io_awaitable_promise_base). The returned executor reflects the executor this coroutine is bound to.

+
+
+
+
+

Example

+
+
+
+
task<void> example()
+{
+    executor_ref ex = co_await this_coro::executor;
+}
+
+
+
+
+
+

Behavior

+
+
+
    +
  • +

    If no executor was set, returns a default‐constructed `executor_ref` (where `operator bool()` returns `false`).

    +
  • +
  • +

    This operation never suspends; `await_ready()` always returns `true`.

    +
  • +
+
+
+
+
+

See Also

+
+
+

executor_tag

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/executor_tag.html b/preview/reference/boost/capy/this_coro/executor_tag.html new file mode 100644 index 0000000..0294481 --- /dev/null +++ b/preview/reference/boost/capy/this_coro/executor_tag.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::this_coro::executor_tag :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::executor_tag

+
+
+
+

Tag type for coroutine executor retrieval.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
struct executor_tag;
+
+
+
+
+
+

Description

+
+
+

This tag is intercepted by a promise type's await_transform to yield the coroutine's current executor. The tag itself carries no data; it serves only as a sentinel for compile‐time dispatch.

+
+
+
+
+

See Also

+
+
+

executor

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/stop_token.html b/preview/reference/boost/capy/this_coro/stop_token.html new file mode 100644 index 0000000..e038f98 --- /dev/null +++ b/preview/reference/boost/capy/this_coro/stop_token.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + boost::capy::this_coro::stop_token :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::stop_token

+
+
+
+

Tag object that yields the current stop token when awaited.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
inline constexpr stop_token_tag stop_token = {};
+
+
+
+
+
+

Description

+
+
+

Use co_await this_coro::stop_token inside a coroutine whose promise type supports stop token access (e.g., inherits from io_awaitable_promise_base). The returned stop token reflects whatever token was passed to this coroutine when it was awaited.

+
+
+
+
+

Example

+
+
+
+
task<void> cancellable_work()
+{
+    auto token = co_await this_coro::stop_token;
+    if (token.stop_requested())
+        co_return;
+}
+
+
+
+
+
+

Behavior

+
+
+
    +
  • +

    If no stop token was propagated, returns a default‐constructed `std::stop_token` (where `stop_possible()` returns `false`).

    +
  • +
  • +

    The returned token remains valid for the coroutine's lifetime.

    +
  • +
  • +

    This operation never suspends; `await_ready()` always returns `true`.

    +
  • +
+
+
+
+
+

See Also

+
+
+

stop_token_tag

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/this_coro/stop_token_tag.html b/preview/reference/boost/capy/this_coro/stop_token_tag.html new file mode 100644 index 0000000..ffceaf6 --- /dev/null +++ b/preview/reference/boost/capy/this_coro/stop_token_tag.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::this_coro::stop_token_tag :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::this_coro::stop_token_tag

+
+
+
+

Tag type for coroutine stop token retrieval.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/ex/this_coro.hpp>

+
+
+
+
struct stop_token_tag;
+
+
+
+
+
+

Description

+
+
+

This tag is intercepted by a promise type's await_transform to yield the coroutine's current stop token. The tag itself carries no data; it serves only as a sentinel for compile‐time dispatch.

+
+
+
+
+

See Also

+
+
+

stop_token

+
+
+

io_awaitable_promise_base

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool.html b/preview/reference/boost/capy/thread_pool.html new file mode 100644 index 0000000..089c300 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool.html @@ -0,0 +1,573 @@ + + + + + + + + + + + + + + boost::capy::thread_pool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool

+
+
+
+

A pool of threads for executing work concurrently.

+
+
+
+
+

Synopsis

+
+ +
+
+
class thread_pool
+    : public execution_context
+
+
+
+
+
+

Description

+
+
+

Use this when you need to run coroutines on multiple threads without the overhead of creating and destroying threads for each task. Work items are distributed across the pool using a shared queue.

+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Unsafe.

+
+
+
+
+

Example

+
+
+
+
thread_pool pool(4);  // 4 worker threads
+auto ex = pool.get_executor();
+ex.post(some_coroutine);
+// pool destructor waits for all work to complete
+
+
+
+
+
+

Base Classes

+
+ ++++ + + + + + + + + + + + + +
NameDescription

execution_context

Base class for I/O object containers providing service management.

+
+
+
+

Types

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

executor_type

An executor that submits work to a thread_pool.

service

Abstract base class for services owned by an execution context.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

thread_pool [constructor] [deleted]

Construct a thread pool.

~thread_pool [destructor]

Destroy the thread pool.

operator= [deleted]

Assignment operators

find_service

Return a pointer to the service of type T, or nullptr.

get_executor

Return an executor for this thread pool.

get_frame_allocator

Return the memory resource used for coroutine frame allocation.

has_service

Return true if a service of type T exists.

make_service

Construct and add a service.

set_frame_allocator

set_frame_allocator overloads

stop

Request all worker threads to stop.

target

Return a pointer to this context if it matches the requested type.

use_service

Return a reference to the service of type T, creating it if needed.

+
+
+
+

Protected Member Functions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Description

destroy

Destroy all services.

shutdown

Shut down all services.

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

get_system_context

Return the process‐wide system execution context.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/2constructor-04.html b/preview/reference/boost/capy/thread_pool/2constructor-04.html new file mode 100644 index 0000000..c1873ce --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/2constructor-04.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::thread_pool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/2constructor-09.html b/preview/reference/boost/capy/thread_pool/2constructor-09.html new file mode 100644 index 0000000..2b6c526 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/2constructor-09.html @@ -0,0 +1,422 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::thread_pool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::thread_pool

+
+
+
+

Construct a thread pool.

+
+
+
+
+

Synopsis

+
+ +
+
+
explicit
+thread_pool(
+    std::size_t num_threads = 0,
+    std::string_view thread_name_prefix = "capy‐pool‐");
+
+
+
+
+
+

Description

+
+
+

Creates a pool with the specified number of worker threads. If num_threads is zero, the number of threads is set to the hardware concurrency, or one if that cannot be determined.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

num_threads

The number of worker threads, or zero for automatic selection.

thread_name_prefix

The prefix for worker thread names. Thread names appear as "{prefix}0", "{prefix}1", etc. The prefix is truncated to 12 characters. Defaults to "capy‐pool‐".

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/2constructor-0f.html b/preview/reference/boost/capy/thread_pool/2constructor-0f.html new file mode 100644 index 0000000..31402e5 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/2constructor-0f.html @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::thread_pool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::thread_pool

+
+
+
+

Construct a thread pool.

+
+
+
+
+

Synopses

+
+ +
+

Copy constructor

+
+
+
+
thread_pool(thread_pool const& other) = delete;
+
+
+ +
+

Construct a thread pool.

+
+
+
+
explicit
+thread_pool(
+    std::size_t num_threads = 0,
+    std::string_view thread_name_prefix = "capy‐pool‐");
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

num_threads

The number of worker threads, or zero for automatic selection.

thread_name_prefix

The prefix for worker thread names. Thread names appear as "{prefix}0", "{prefix}1", etc. The prefix is truncated to 12 characters. Defaults to "capy‐pool‐".

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/2destructor.html b/preview/reference/boost/capy/thread_pool/2destructor.html new file mode 100644 index 0000000..b496530 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/2destructor.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::~thread_pool :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type.html b/preview/reference/boost/capy/thread_pool/executor_type.html new file mode 100644 index 0000000..4f16c15 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type.html @@ -0,0 +1,468 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::executor_type

+
+
+
+

An executor that submits work to a thread_pool.

+
+
+
+
+

Synopsis

+
+ +
+
+
class executor_type;
+
+
+
+
+
+

Description

+
+
+

Executors are lightweight handles that can be copied and stored. All copies refer to the same underlying thread pool.

+
+
+
+
+

Thread Safety

+
+
+

Distinct objects: Safe. Shared objects: Safe.

+
+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

executor_type [constructor]

Default construct a null executor.

context

Return the underlying thread pool.

dispatch

Dispatch a coroutine for execution.

on_work_finished

Notify that work has finished (no‐op for thread pools).

on_work_started

Notify that work has started (no‐op for thread pools).

post

Post a coroutine to the thread pool.

operator==

Return true if two executors refer to the same thread pool.

+
+
+
+

Friends

+
+ ++++ + + + + + + + + + + + + +
NameDescription

boost::capy::thread_pool

A pool of threads for executing work concurrently.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/2constructor.html b/preview/reference/boost/capy/thread_pool/executor_type/2constructor.html new file mode 100644 index 0000000..8d86658 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/2constructor.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::executor_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/context.html b/preview/reference/boost/capy/thread_pool/executor_type/context.html new file mode 100644 index 0000000..323764f --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/context.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::context :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/dispatch.html b/preview/reference/boost/capy/thread_pool/executor_type/dispatch.html new file mode 100644 index 0000000..9965e84 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/dispatch.html @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::dispatch :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::executor_type::dispatch

+
+
+
+

Dispatch a coroutine for execution.

+
+
+
+
+

Synopsis

+
+ +
+
+
std::coroutine_handle
+dispatch(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

Posts the coroutine to the thread pool for execution on a worker thread and returns std::noop_coroutine(). Thread pools never execute inline because no single thread "owns" the pool.

+
+
+
+
+

Return Value

+
+
+

std::noop_coroutine() always.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to execute.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/on_work_finished.html b/preview/reference/boost/capy/thread_pool/executor_type/on_work_finished.html new file mode 100644 index 0000000..45883d5 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/on_work_finished.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::on_work_finished :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/on_work_started.html b/preview/reference/boost/capy/thread_pool/executor_type/on_work_started.html new file mode 100644 index 0000000..892e275 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/on_work_started.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::on_work_started :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/operator_eq.html b/preview/reference/boost/capy/thread_pool/executor_type/operator_eq.html new file mode 100644 index 0000000..5638fcd --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/operator_eq.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::operator== :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::executor_type::operator==

+
+
+
+

Return true if two executors refer to the same thread pool.

+
+
+
+
+

Synopsis

+
+ +
+
+
bool
+operator==(executor_type const& other) const noexcept;
+
+
+
+
+
+

Return Value

+
+
+

true if two executors refer to the same thread pool.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The right operand

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/executor_type/post.html b/preview/reference/boost/capy/thread_pool/executor_type/post.html new file mode 100644 index 0000000..411687d --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/executor_type/post.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::executor_type::post :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::executor_type::post

+
+
+
+

Post a coroutine to the thread pool.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+post(std::coroutine_handle h) const;
+
+
+
+
+
+

Description

+
+
+

The coroutine will be resumed on one of the pool's worker threads.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

h

The coroutine handle to execute.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/get_executor.html b/preview/reference/boost/capy/thread_pool/get_executor.html new file mode 100644 index 0000000..e60d1fc --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/get_executor.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::get_executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/operator_assign-0d.html b/preview/reference/boost/capy/thread_pool/operator_assign-0d.html new file mode 100644 index 0000000..b2fda40 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/operator_assign-0d.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/operator_assign-0f.html b/preview/reference/boost/capy/thread_pool/operator_assign-0f.html new file mode 100644 index 0000000..519499e --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/operator_assign-0f.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::thread_pool::operator=

+
+
+
+

Assignment operators

+
+
+
+
+

Synopses

+
+ +
+

Copy assignment operator

+
+
+
+
execution_context&
+operator=(execution_context const& other) = delete;
+
+
+ +
+

Copy assignment operator

+
+
+
+
thread_pool&
+operator=(thread_pool const& other) = delete;
+
+
+ +
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/thread_pool/stop.html b/preview/reference/boost/capy/thread_pool/stop.html new file mode 100644 index 0000000..f07dcc4 --- /dev/null +++ b/preview/reference/boost/capy/thread_pool/stop.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + boost::capy::thread_pool::stop :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/vector_dynamic_buffer.html b/preview/reference/boost/capy/vector_dynamic_buffer.html new file mode 100644 index 0000000..3e7d95b --- /dev/null +++ b/preview/reference/boost/capy/vector_dynamic_buffer.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::vector_dynamic_buffer :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/when_all.html b/preview/reference/boost/capy/when_all.html new file mode 100644 index 0000000..61526e6 --- /dev/null +++ b/preview/reference/boost/capy/when_all.html @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + boost::capy::when_all :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::when_all

+
+
+
+

Execute multiple awaitables concurrently and collect their results.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/when_all.hpp>

+
+
+
+
template<IoAwaitable... As>
+[[nodiscard]]
+task</* implementation-defined */>
+when_all(As... awaitables);
+
+
+
+
+
+

Description

+
+
+

Launches all awaitables simultaneously and waits for all to complete before returning. Results are collected in input order. If any awaitable throws, cancellation is requested for siblings and the first exception is rethrown after all awaitables complete.

+
+
+
    +
  • +

    All child awaitables run concurrently on the caller's executor

    +
  • +
  • +

    Results are returned as a tuple in input order

    +
  • +
  • +

    Void‐returning awaitables do not contribute to the result tuple

    +
  • +
  • +

    If all awaitables return void, `when_all` returns `task<void>`

    +
  • +
  • +

    First exception wins; subsequent exceptions are discarded

    +
  • +
  • +

    Stop is requested for siblings on first error

    +
  • +
  • +

    Completes only after all children have finished

    +
  • +
+
+
+
+
+

Thread Safety

+
+
+

The returned task must be awaited from a single execution context. Child awaitables execute concurrently but complete through the caller's executor.

+
+
+
+
+

Example

+
+
+
+
task<> example()
+{
+    // Concurrent fetch, results collected in order
+    auto [user, posts] = co_await when_all(
+        fetch_user( id ),      // task<User>
+        fetch_posts( id )      // task<std::vector<Post>>
+    );
+
+    // Void awaitables don't contribute to result
+    co_await when_all(
+        log_event( "start" ),  // task<void>
+        notify_user( id )      // task<void>
+    );
+    // Returns task<void>, no result tuple
+}
+
+
+
+
+
+

Return Value

+
+
+

A task yielding a tuple of non‐void results. Returns task<void> when all input awaitables return void.

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

awaitables

The awaitables to execute concurrently. Each must satisfy IoAwaitable and is consumed (moved‐from) when when_all is awaited.

+
+
+
+

See Also

+
+
+

IoAwaitable, task

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/when_all_result_type.html b/preview/reference/boost/capy/when_all_result_type.html new file mode 100644 index 0000000..f078a3b --- /dev/null +++ b/preview/reference/boost/capy/when_all_result_type.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + boost::capy::when_all_result_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::when_all_result_type

+
+
+
+

Compute the result type of when_all for the given task types.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/when_all.hpp>

+
+
+
+
template<typename... Ts>
+using when_all_result_type = /* implementation-defined */;
+
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/when_any-09.html b/preview/reference/boost/capy/when_any-09.html new file mode 100644 index 0000000..0ee81f7 --- /dev/null +++ b/preview/reference/boost/capy/when_any-09.html @@ -0,0 +1,615 @@ + + + + + + + + + + + + + + boost::capy::when_any :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::when_any

+
+
+
+

Wait for the first awaitable to complete (void range overload).

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/when_any.hpp>

+
+
+
+
template<IoAwaitableRange R>
+requires std::is_void_v<detail::awaitable_result_t<std::ranges::range_value_t<R>>>
+[[nodiscard]]
+task<std::size_t>
+when_any(R&& awaitables);
+
+
+
+
+
+

Description

+
+
+

Races a range of void‐returning awaitables. Since void awaitables have no result value, only the winner's index is returned.

+
+
+
+
+

Suspends

+
+
+

The calling coroutine suspends when co_await is invoked. All awaitables in the range are launched concurrently and execute in parallel. The coroutine resumes only after all awaitables have completed, even though the winner is determined by the first to finish.

+
+
+
+
+

Completion Conditions

+
+
+
    +
  • +

    Winner is determined when the first awaitable completes (success or exception)

    +
  • +
  • +

    Only one task can claim winner status via atomic compare‐exchange

    +
  • +
  • +

    Once a winner exists, stop is requested for all remaining siblings

    +
  • +
  • +

    Parent coroutine resumes only after all siblings acknowledge completion

    +
  • +
  • +

    The winner's index is returned; if the winner threw, the exception is rethrown

    +
  • +
+
+
+
+
+

Cancellation Semantics

+
+
+

Cancellation is supported via stop_token propagated through the IoAwaitable protocol:

+
+
+
    +
  • +

    Each child awaitable receives a stop_token derived from a shared stop_source

    +
  • +
  • +

    When the parent's stop token is activated, the stop is forwarded to all children

    +
  • +
  • +

    When a winner is determined, stop_source_.request_stop() is called immediately

    +
  • +
  • +

    Siblings must handle cancellation gracefully and complete before parent resumes

    +
  • +
  • +

    Stop requests are cooperative; tasks must check and respond to them

    +
  • +
+
+
+
+
+

Concurrency/Overlap

+
+
+

All awaitables are launched concurrently before any can complete. The launcher iterates through the range, starting each task on the caller's executor. Tasks may execute in parallel on multi‐threaded executors or interleave on single‐threaded executors. There is no guaranteed ordering of task completion.

+
+
+
+
+

Notable Error Conditions

+
+
+
    +
  • +

    Empty range: throws std::invalid_argument immediately (not via co_return)

    +
  • +
  • +

    Winner exception: if the winning task threw, that exception is rethrown

    +
  • +
  • +

    Non‐winner exceptions: silently discarded (only winner's result matters)

    +
  • +
  • +

    Cancellation: tasks may complete via cancellation without throwing

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<void> example() {
+    std::vector<task<void>> tasks;
+    for (int i = 0; i < 5; ++i)
+        tasks.push_back(background_work(i));
+
+    std::size_t winner = co_await when_any(std::move(tasks));
+    // winner is the index of the first task to complete
+}
+
+
+
+
+
+

Example with Timeout

+
+
+
+
task<void> with_timeout() {
+    std::vector<task<void>> tasks;
+    tasks.push_back(long_running_operation());
+    tasks.push_back(delay(std::chrono::seconds(5)));
+
+    std::size_t winner = co_await when_any(std::move(tasks));
+    if (winner == 1) {
+        // Timeout occurred
+    }
+}
+
+
+
+
+
+

Remarks

+
+
+

Elements are moved from the range; for lvalue ranges, the original container will have moved‐from elements after this call. The range is moved onto the coroutine frame to ensure lifetime safety. Unlike the non‐void overload, no result storage is needed since void tasks produce no value.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if range is empty (thrown before coroutine suspends).

Rethrows

the winner's exception if the winning task threw an exception.

+
+
+
+

Return Value

+
+
+

A task yielding the winner's index (zero‐based).

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

R

Range type satisfying IoAwaitableRange with void result.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

awaitables

Range of void awaitables to race concurrently (must not be empty).

+
+
+
+

See Also

+
+
+

when_any, IoAwaitableRange

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/when_any-0d8.html b/preview/reference/boost/capy/when_any-0d8.html new file mode 100644 index 0000000..f9648d7 --- /dev/null +++ b/preview/reference/boost/capy/when_any-0d8.html @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + boost::capy::when_any :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::when_any

+
+
+
+

when_any overloads

+
+
+
+
+

Synopses

+
+
+

Declared in <boost/capy/when_any.hpp>

+
+
+

Wait for the first awaitable to complete (range overload).

+
+
+
+
template<IoAwaitableRange R>
+requires (!std::is_void_v<detail::awaitable_result_t<std::ranges::range_value_t<R>>>)
+[[nodiscard]]
+task<std::pair<std::size_t, /* implementation-defined */>>
+when_any(R&& awaitables);
+
+
+ +
+

Wait for the first awaitable to complete (void range overload).

+
+
+
+
template<IoAwaitableRange R>
+requires std::is_void_v<detail::awaitable_result_t<std::ranges::range_value_t<R>>>
+[[nodiscard]]
+task<std::size_t>
+when_any(R&& awaitables);
+
+
+ +
+

Wait for the first awaitable to complete.

+
+
+
+
template<
+    IoAwaitable A0,
+    IoAwaitable... As>
+[[nodiscard]]
+task</* implementation-defined */>
+when_any(
+    A0 a0,
+    As... as);
+
+
+ +
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if range is empty (thrown before coroutine suspends).

Rethrows

the winner's exception if the winning task threw an exception.

+
+
+
+

Return Value

+
+
+
    +
  • +

    A task yielding a pair of (winner_index, result).

    +
  • +
  • +

    A task yielding the winner's index (zero‐based).

    +
  • +
  • +

    A task yielding a pair of (winner_index, result_variant).

    +
  • +
+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

R

Range type satisfying IoAwaitableRange.

A0

First awaitable type (must satisfy IoAwaitable).

As

Remaining awaitable types (must satisfy IoAwaitable).

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + + + + + +
NameDescription

awaitables

Range of awaitables to race concurrently (must not be empty).

a0

The first awaitable to race.

as

Additional awaitables to race concurrently.

+
+
+
+

See Also

+
+
+

when_any, IoAwaitableRange

+
+
+

when_all, IoAwaitable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/when_any-0da.html b/preview/reference/boost/capy/when_any-0da.html new file mode 100644 index 0000000..4480ebe --- /dev/null +++ b/preview/reference/boost/capy/when_any-0da.html @@ -0,0 +1,619 @@ + + + + + + + + + + + + + + boost::capy::when_any :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::when_any

+
+
+
+

Wait for the first awaitable to complete.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/when_any.hpp>

+
+
+
+
template<
+    IoAwaitable A0,
+    IoAwaitable... As>
+[[nodiscard]]
+task</* implementation-defined */>
+when_any(
+    A0 a0,
+    As... as);
+
+
+
+
+
+

Description

+
+
+

Races multiple heterogeneous awaitables concurrently and returns when the first one completes. The result includes the winner's index and a deduplicated variant containing the result value.

+
+
+
+
+

Suspends

+
+
+

The calling coroutine suspends when co_await is invoked. All awaitables are launched concurrently and execute in parallel. The coroutine resumes only after all awaitables have completed, even though the winner is determined by the first to finish.

+
+
+
+
+

Completion Conditions

+
+
+
    +
  • +

    Winner is determined when the first awaitable completes (success or exception)

    +
  • +
  • +

    Only one task can claim winner status via atomic compare‐exchange

    +
  • +
  • +

    Once a winner exists, stop is requested for all remaining siblings

    +
  • +
  • +

    Parent coroutine resumes only after all siblings acknowledge completion

    +
  • +
  • +

    The winner's result is returned; if the winner threw, the exception is rethrown

    +
  • +
+
+
+
+
+

Cancellation Semantics

+
+
+

Cancellation is supported via stop_token propagated through the IoAwaitable protocol:

+
+
+
    +
  • +

    Each child awaitable receives a stop_token derived from a shared stop_source

    +
  • +
  • +

    When the parent's stop token is activated, the stop is forwarded to all children

    +
  • +
  • +

    When a winner is determined, stop_source_.request_stop() is called immediately

    +
  • +
  • +

    Siblings must handle cancellation gracefully and complete before parent resumes

    +
  • +
  • +

    Stop requests are cooperative; tasks must check and respond to them

    +
  • +
+
+
+
+
+

Concurrency/Overlap

+
+
+

All awaitables are launched concurrently before any can complete. The launcher iterates through the arguments, starting each task on the caller's executor. Tasks may execute in parallel on multi‐threaded executors or interleave on single‐threaded executors. There is no guaranteed ordering of task completion.

+
+
+
+
+

Notable Error Conditions

+
+
+
    +
  • +

    Winner exception: if the winning task threw, that exception is rethrown

    +
  • +
  • +

    Non‐winner exceptions: silently discarded (only winner's result matters)

    +
  • +
  • +

    Cancellation: tasks may complete via cancellation without throwing

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<void> example() {
+    auto [index, result] = co_await when_any(
+        fetch_from_primary(),   // task<Response>
+        fetch_from_backup()     // task<Response>
+    );
+    // index is 0 or 1, result holds the winner's Response
+    auto response = std::get<Response>(result);
+}
+
+
+
+
+
+

Example with Heterogeneous Types

+
+
+
+
task<void> mixed_types() {
+    auto [index, result] = co_await when_any(
+        fetch_int(),      // task<int>
+        fetch_string()    // task<std::string>
+    );
+    if (index == 0)
+        std::cout << "Got int: " << std::get<int>(result) << "\n";
+    else
+        std::cout << "Got string: " << std::get<std::string>(result) << "\n";
+}
+
+
+
+
+
+

Remarks

+
+
+

Awaitables are moved into the coroutine frame; original objects become empty after the call. When multiple awaitables share the same return type, the variant is deduplicated to contain only unique types. Use the winner index to determine which awaitable completed first. Void awaitables contribute std::monostate to the variant.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + +

Name

Thrown on

Rethrows

the winner's exception if the winning task threw an exception.

+
+
+
+

Return Value

+
+
+

A task yielding a pair of (winner_index, result_variant).

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

A0

First awaitable type (must satisfy IoAwaitable).

As

Remaining awaitable types (must satisfy IoAwaitable).

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

a0

The first awaitable to race.

as

Additional awaitables to race concurrently.

+
+
+
+

See Also

+
+
+

when_all, IoAwaitable

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/when_any-0f.html b/preview/reference/boost/capy/when_any-0f.html new file mode 100644 index 0000000..d1900cd --- /dev/null +++ b/preview/reference/boost/capy/when_any-0f.html @@ -0,0 +1,614 @@ + + + + + + + + + + + + + + boost::capy::when_any :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::when_any

+
+
+
+

Wait for the first awaitable to complete (range overload).

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/when_any.hpp>

+
+
+
+
template<IoAwaitableRange R>
+requires (!std::is_void_v<detail::awaitable_result_t<std::ranges::range_value_t<R>>>)
+[[nodiscard]]
+task<std::pair<std::size_t, /* implementation-defined */>>
+when_any(R&& awaitables);
+
+
+
+
+
+

Description

+
+
+

Races a range of awaitables with the same result type. Accepts any sized input range of IoAwaitable types, enabling use with arrays, spans, or custom containers.

+
+
+
+
+

Suspends

+
+
+

The calling coroutine suspends when co_await is invoked. All awaitables in the range are launched concurrently and execute in parallel. The coroutine resumes only after all awaitables have completed, even though the winner is determined by the first to finish.

+
+
+
+
+

Completion Conditions

+
+
+
    +
  • +

    Winner is determined when the first awaitable completes (success or exception)

    +
  • +
  • +

    Only one task can claim winner status via atomic compare‐exchange

    +
  • +
  • +

    Once a winner exists, stop is requested for all remaining siblings

    +
  • +
  • +

    Parent coroutine resumes only after all siblings acknowledge completion

    +
  • +
  • +

    The winner's index and result are returned; if the winner threw, the exception is rethrown

    +
  • +
+
+
+
+
+

Cancellation Semantics

+
+
+

Cancellation is supported via stop_token propagated through the IoAwaitable protocol:

+
+
+
    +
  • +

    Each child awaitable receives a stop_token derived from a shared stop_source

    +
  • +
  • +

    When the parent's stop token is activated, the stop is forwarded to all children

    +
  • +
  • +

    When a winner is determined, stop_source_.request_stop() is called immediately

    +
  • +
  • +

    Siblings must handle cancellation gracefully and complete before parent resumes

    +
  • +
  • +

    Stop requests are cooperative; tasks must check and respond to them

    +
  • +
+
+
+
+
+

Concurrency/Overlap

+
+
+

All awaitables are launched concurrently before any can complete. The launcher iterates through the range, starting each task on the caller's executor. Tasks may execute in parallel on multi‐threaded executors or interleave on single‐threaded executors. There is no guaranteed ordering of task completion.

+
+
+
+
+

Notable Error Conditions

+
+
+
    +
  • +

    Empty range: throws std::invalid_argument immediately (not via co_return)

    +
  • +
  • +

    Winner exception: if the winning task threw, that exception is rethrown

    +
  • +
  • +

    Non‐winner exceptions: silently discarded (only winner's result matters)

    +
  • +
  • +

    Cancellation: tasks may complete via cancellation without throwing

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<void> example() {
+    std::array<task<Response>, 3> requests = {
+        fetch_from_server(0),
+        fetch_from_server(1),
+        fetch_from_server(2)
+    };
+
+    auto [index, response] = co_await when_any(std::move(requests));
+}
+
+
+
+
+
+

Example with Vector

+
+
+
+
task<Response> fetch_fastest(std::vector<Server> const& servers) {
+    std::vector<task<Response>> requests;
+    for (auto const& server : servers)
+        requests.push_back(fetch_from(server));
+
+    auto [index, response] = co_await when_any(std::move(requests));
+    co_return response;
+}
+
+
+
+
+
+

Remarks

+
+
+

Elements are moved from the range; for lvalue ranges, the original container will have moved‐from elements after this call. The range is moved onto the coroutine frame to ensure lifetime safety. Unlike the variadic overload, no variant wrapper is needed since all tasks share the same return type.

+
+
+
+
+

Exceptions

+
+ ++++ + + + + + + + + + + + + + + +

Name

Thrown on

std::invalid_argument

if range is empty (thrown before coroutine suspends).

Rethrows

the winner's exception if the winning task threw an exception.

+
+
+
+

Return Value

+
+
+

A task yielding a pair of (winner_index, result).

+
+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

R

Range type satisfying IoAwaitableRange.

+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

awaitables

Range of awaitables to race concurrently (must not be empty).

+
+
+
+

See Also

+
+
+

when_any, IoAwaitableRange

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard.html b/preview/reference/boost/capy/work_guard.html new file mode 100644 index 0000000..d7f2aac --- /dev/null +++ b/preview/reference/boost/capy/work_guard.html @@ -0,0 +1,575 @@ + + + + + + + + + + + + + + boost::capy::work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard

+
+
+
+

RAII guard that keeps an executor's context from completing.

+
+
+
+
+

Synopsis

+
+ +
+
+
template<Executor Ex>
+class work_guard;
+
+
+
+
+
+

Description

+
+
+

This class holds "work" on an executor, preventing the associated execution context's run() function from returning due to lack of work. It calls on_work_started() on construction and on_work_finished() on destruction, ensuring proper work tracking.

+
+
+

The guard is useful when you need to keep an execution context running while waiting for external events or when work will be posted later.

+
+
+
+
+

RAII Semantics

+
+
+
    +
  • +

    Construction calls `ex.on_work_started()`.

    +
  • +
  • +

    Destruction calls `ex.on_work_finished()` if `owns_work()`.

    +
  • +
  • +

    Copy construction creates a new work reference (calls `on_work_started()` again).

    +
  • +
  • +

    Move construction transfers ownership without additional calls.

    +
  • +
+
+
+
+
+

Thread Safety

+
+
+

Distinct objects may be accessed concurrently. Access to a single object requires external synchronization.

+
+
+
+
+

Example

+
+
+
+
io_context ctx;
+
+// Keep context running while we set things up
+auto guard = make_work_guard(ctx);
+
+std::thread t([&ctx]{ ctx.run(); });
+
+// ... post work to ctx ...
+
+// Allow context to complete when work is done
+guard.reset();
+
+t.join();
+
+
+
+ + + + + +
+ + +
+

The executor is returned by reference, allowing callers to manage the executor's lifetime directly. This is essential in coroutine‐first designs where the executor often outlives individual coroutine frames.

+
+
+
+
+
+
+

Types

+
+ ++++ + + + + + + + + + + +

Name

Description

executor_type

The underlying executor type.

+
+
+
+

Member Functions

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

work_guard [constructor]

Constructors

~work_guard [destructor]

Destructor.

operator= [deleted]

Copy assignment operator

executor

Return the underlying executor by reference.

owns_work

Return whether the guard owns work.

reset

Release ownership of the work.

+
+
+
+

Non-Member Functions

+
+ ++++ + + + + + + + + + + +

Name

Description

make_work_guard

Create a work guard from an executor.

+
+
+
+

Template Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

Ex

A type satisfying the Executor concept.

+
+
+
+

See Also

+
+
+

make_work_guard, Executor

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/2constructor-074.html b/preview/reference/boost/capy/work_guard/2constructor-074.html new file mode 100644 index 0000000..9a26011 --- /dev/null +++ b/preview/reference/boost/capy/work_guard/2constructor-074.html @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + boost::capy::work_guard::work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard::work_guard

+
+
+
+

Construct a work guard.

+
+
+
+
+

Synopsis

+
+ +
+
+
explicit
+work_guard(Ex ex) noexcept;
+
+
+
+
+
+

Description

+
+
+

Calls ex.on_work_started() to inform the executor that work is outstanding.

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `owns_work() == true`

    +
  • +
  • +

    `executor() == ex`

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

ex

The executor to hold work on. Moved into the guard.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/2constructor-075.html b/preview/reference/boost/capy/work_guard/2constructor-075.html new file mode 100644 index 0000000..e1ad620 --- /dev/null +++ b/preview/reference/boost/capy/work_guard/2constructor-075.html @@ -0,0 +1,438 @@ + + + + + + + + + + + + + + boost::capy::work_guard::work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard::work_guard

+
+
+
+

Move constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
work_guard(work_guard&& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Transfers work ownership from other to *this. Does not call on_work_started() or on_work_finished().

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `owns_work()` equals the prior value of `other.owns_work()`

    +
  • +
  • +

    `other.owns_work() == false`

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The work guard to move from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/2constructor-07d.html b/preview/reference/boost/capy/work_guard/2constructor-07d.html new file mode 100644 index 0000000..0397c89 --- /dev/null +++ b/preview/reference/boost/capy/work_guard/2constructor-07d.html @@ -0,0 +1,438 @@ + + + + + + + + + + + + + + boost::capy::work_guard::work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard::work_guard

+
+
+
+

Copy constructor.

+
+
+
+
+

Synopsis

+
+ +
+
+
work_guard(work_guard const& other) noexcept;
+
+
+
+
+
+

Description

+
+
+

Creates a new work guard holding work on the same executor. Calls on_work_started() on the executor.

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `owns_work() == other.owns_work()`

    +
  • +
  • +

    `executor() == other.executor()`

    +
  • +
+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + +
NameDescription

other

The work guard to copy from.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/2constructor-0f.html b/preview/reference/boost/capy/work_guard/2constructor-0f.html new file mode 100644 index 0000000..c4cf35f --- /dev/null +++ b/preview/reference/boost/capy/work_guard/2constructor-0f.html @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + boost::capy::work_guard::work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard::work_guard

+
+
+
+

Constructors

+
+
+
+
+

Synopses

+
+ +
+

Copy constructor.

+
+
+
+
work_guard(work_guard const& other) noexcept;
+
+
+ +
+

Move constructor.

+
+
+
+
work_guard(work_guard&& other) noexcept;
+
+
+ +
+

Construct a work guard.

+
+
+
+
explicit
+work_guard(Ex ex) noexcept;
+
+
+ +
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

other

The work guard to copy from.

ex

The executor to hold work on. Moved into the guard.

+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/2destructor.html b/preview/reference/boost/capy/work_guard/2destructor.html new file mode 100644 index 0000000..c0afc5b --- /dev/null +++ b/preview/reference/boost/capy/work_guard/2destructor.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + boost::capy::work_guard::~work_guard :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/executor.html b/preview/reference/boost/capy/work_guard/executor.html new file mode 100644 index 0000000..b8eeefc --- /dev/null +++ b/preview/reference/boost/capy/work_guard/executor.html @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + boost::capy::work_guard::executor :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard::executor

+
+
+
+

Return the underlying executor by reference.

+
+
+
+
+

Synopsis

+
+ +
+
+
executor_type const&
+executor() const noexcept;
+
+
+
+
+
+

Description

+
+
+

The reference remains valid for the lifetime of this guard, enabling callers to manage executor lifetime explicitly.

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Return Value

+
+
+

A reference to the stored executor.

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/executor_type.html b/preview/reference/boost/capy/work_guard/executor_type.html new file mode 100644 index 0000000..56f9b8e --- /dev/null +++ b/preview/reference/boost/capy/work_guard/executor_type.html @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + boost::capy::work_guard::executor_type :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/operator_assign.html b/preview/reference/boost/capy/work_guard/operator_assign.html new file mode 100644 index 0000000..f955c0a --- /dev/null +++ b/preview/reference/boost/capy/work_guard/operator_assign.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + boost::capy::work_guard::operator= :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/owns_work.html b/preview/reference/boost/capy/work_guard/owns_work.html new file mode 100644 index 0000000..d788e3a --- /dev/null +++ b/preview/reference/boost/capy/work_guard/owns_work.html @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + boost::capy::work_guard::owns_work :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + diff --git a/preview/reference/boost/capy/work_guard/reset.html b/preview/reference/boost/capy/work_guard/reset.html new file mode 100644 index 0000000..f9afc7e --- /dev/null +++ b/preview/reference/boost/capy/work_guard/reset.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + boost::capy::work_guard::reset :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::work_guard::reset

+
+
+
+

Release ownership of the work.

+
+
+
+
+

Synopsis

+
+ +
+
+
void
+reset() noexcept;
+
+
+
+
+
+

Description

+
+
+

If owns_work() is true, calls on_work_finished() on the executor and sets ownership to false. Otherwise, has no effect.

+
+
+
+
+

Exception Safety

+
+
+

No‐throw guarantee.

+
+
+
+
+

Postconditions

+
+
+
    +
  • +

    `owns_work() == false`

    +
  • +
+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/boost/capy/write.html b/preview/reference/boost/capy/write.html new file mode 100644 index 0000000..10ddc75 --- /dev/null +++ b/preview/reference/boost/capy/write.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + boost::capy::write :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

boost::capy::write

+
+
+
+

Asynchronously write the entire buffer sequence.

+
+
+
+
+

Synopsis

+
+
+

Declared in <boost/capy/write.hpp>

+
+
+
+
io_task<std::size_t>
+write(
+    auto& stream,
+    auto const& buffers);
+
+
+
+
+
+

Description

+
+
+

Writes data to the stream by calling write_some repeatedly until the entire buffer sequence is written or an error occurs.

+
+
+
    +
  • +

    The operation completes when:

    +
  • +
  • +

    The entire buffer sequence has been written

    +
  • +
  • +

    An error occurs

    +
  • +
  • +

    The operation is cancelled

    +
  • +
+
+
+
+
+

Cancellation

+
+
+

Supports cancellation via stop_token propagated through the IoAwaitable protocol. When cancelled, returns with cond::canceled.

+
+
+
    +
  • +

    `cond::canceled` ‐ Operation was cancelled

    +
  • +
  • +

    `std::errc::broken_pipe` ‐ Peer closed connection

    +
  • +
+
+
+
+
+

Example

+
+
+
+
task<> send_response( WriteStream auto& stream, std::string_view body )
+{
+    auto [ec, n] = co_await write( stream, make_buffer( body ) );
+    if( ec )
+        detail::throw_system_error( ec );
+    // All bytes written successfully
+}
+
+
+
+
+
+

Return Value

+
+
+

An awaitable yielding (error_code, std::size_t). On success, n equals buffer_size(buffers). On error, n is the number of bytes written before the error. Compare error codes to conditions:

+
+
+
+
+

Parameters

+
+ ++++ + + + + + + + + + + + + + + + + +
NameDescription

stream

The stream to write to. The caller retains ownership.

buffers

The buffer sequence to write. The caller retains ownership and must ensure validity until the operation completes.

+
+
+
+

See Also

+
+
+

write_some, WriteStream, ConstBufferSequence

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/reference/index.html b/preview/reference/index.html new file mode 100644 index 0000000..7d49b9b --- /dev/null +++ b/preview/reference/index.html @@ -0,0 +1,1099 @@ + + + + + + + + + + + + + + Global namespace :: Boost Libraries Documentation + + + + + + + + + + + + + + + + +
+
+
+ +

Global namespace

+
+

Namespaces

+
+ +++ + + + + + + + + +

Name

boost

+
+
+
+

boost namespace

+
+
+

Namespaces

+ +++ + + + + + + + + +

Name

capy

+
+
+
+
+

boost::capy namespace

+
+
+

Namespaces

+ ++++ + + + + + + + + + + +

Name

Description

this_coro

Namespace for coroutine environment accessors.

+
+
+

Types

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

any_buffer_sink

Type‐erased wrapper for any BufferSink.

any_buffer_source

Type‐erased wrapper for any BufferSource.

any_executor

A type‐erased wrapper for executor objects.

any_read_source

Type‐erased wrapper for any ReadSource.

any_read_stream

Type‐erased wrapper for any ReadStream.

any_stream

Type‐erased wrapper for bidirectional streams.

any_write_sink

Type‐erased wrapper for any WriteSink.

any_write_stream

Type‐erased wrapper for any WriteStream.

async_event

An asynchronous event for coroutines.

async_mutex

An asynchronous mutex for coroutines.

basic_string_dynamic_buffer

A dynamic buffer using an underlying string

basic_vector_dynamic_buffer

A dynamic buffer using an underlying vector.

basic_vector_dynamic_buffer

A dynamic buffer using an underlying vector.

begin_mrdocs_workaround_t

Return an iterator to the first buffer in a sequence.

buffer_array

A buffer sequence holding up to N buffers.

buffer_copy_mrdocs_workaround_t

Copy the contents of a buffer sequence into another buffer sequence.

buffer_empty_mrdocs_workaround_t

Check if a buffer sequence contains no data.

buffer_param

A buffer sequence wrapper providing windowed access.

buffer_param

A buffer sequence wrapper providing windowed access.

buffer_size_mrdocs_workaround_t

Return the total byte count across all buffers in a sequence.

circular_dynamic_buffer

A fixed‐capacity circular buffer satisfying DynamicBuffer.

const_buffer

A reference to a contiguous region of read‐only memory.

const_buffer_archetype_

Archetype for ConstBufferSequence concept checking.

consuming_buffers

Wrapper for consuming a buffer sequence incrementally.

consuming_buffers

Wrapper for consuming a buffer sequence incrementally.

end_mrdocs_workaround_t

Return an iterator past the last buffer in a sequence.

execution_context

Base class for I/O object containers providing service management.

executor_ref

A type‐erased reference wrapper for executor objects.

flat_dynamic_buffer

A fixed‐capacity linear buffer satisfying DynamicBuffer.

front_mrdocs_workaround_t

Return the first buffer in a sequence.

immediate

An awaitable that completes immediately with a value.

io_awaitable_promise_base

CRTP mixin that adds I/O awaitable support to a promise type.

io_env

Execution environment for IoAwaitables.

io_result<>

Result type for void operations.

io_result

Result type for asynchronous I/O operations.

io_result<T1>

Result type for byte transfer operations.

io_result<T1, T2>

io_result<T1, T2, T3>

keep_prefix_mrdocs_workaround_t

Remove all but the first n bytes from a buffer sequence

keep_suffix_mrdocs_workaround_t

Remove all but the last n bytes from a buffer sequence

match_delim

Match condition that searches for a delimiter string.

mutable_buffer

A reference to a contiguous region of writable memory.

mutable_buffer_archetype_

Archetype for MutableBufferSequence concept checking.

prefix_mrdocs_workaround_t

Return a sequence representing the first n bytes of a buffer sequence

recycling_memory_resource

remove_prefix_mrdocs_workaround_t

Remove n bytes from the beginning of a buffer sequence

remove_suffix_mrdocs_workaround_t

Remove n bytes from the end of a buffer sequence

run_async_wrapper

Wrapper returned by run_async that accepts a task for execution.

sans_prefix_mrdocs_workaround_t

Return a sequence representing all but the first n bytes of a buffer sequence

sans_suffix_mrdocs_workaround_t

Return a sequence representing all but the last n bytes of a buffer sequence

size_tag

Tag type for customizing buffer_size via tag_invoke.

slice_of

slice_of<BufferSequence>

A wrapper enabling a buffer sequence to be consumed

slice_tag

Tag type for customizing slice operations via tag_invoke.

strand

Provides serialized coroutine execution for any executor type.

suffix_mrdocs_workaround_t

Return a sequence representing the last n bytes of a buffer sequence

task

Lazy coroutine task satisfying IoRunnable.

thread_pool

A pool of threads for executing work concurrently.

work_guard

RAII guard that keeps an executor's context from completing.

buffer_type

Alias for mutable_buffer or const_buffer based on sequence type.

const_buffer_archetype

const_buffer_array

Alias for buffer_array holding const_buffer.

const_buffer_pair

A constant buffer pair

const_buffer_param

Alias for buffer_param that always uses const_buffer storage.

io_task

A task type for I/O operations yielding io_result.

mutable_buffer_archetype

mutable_buffer_array

Alias for buffer_array holding mutable_buffer.

mutable_buffer_pair

A mutable buffer pair

slice_type

Alias for the type representing a slice of T

string_dynamic_buffer

vector_dynamic_buffer

A dynamic buffer using std::vector<unsigned char>.

when_all_result_type

Compute the result type of when_all for the given task types.

+
+
+

Enums

+ ++++ + + + + + + + + + + + + + + + + + + +

Name

Description

cond

Portable error conditions for capy I/O operations.

error

Error codes for capy I/O operations.

slice_how

Constants for slice customization.

+
+
+

Functions

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

buffer_length

Return the number of buffer elements in a sequence.

dynamic_buffer

dynamic_buffer overloads

get_current_frame_allocator

Return the current frame allocator for this thread.

get_recycling_memory_resource

Returns pointer to the default recycling memory resource.

get_system_context

Return the process‐wide system execution context.

make_buffer

make_buffer overloads

make_error_code

make_error_condition

make_work_guard

Create a work guard from an executor.

pull_from

pull_from overloads

push_to

push_to overloads

read

read overloads

read_until

read_until overloads

ready

ready overloads

run

run overloads

run_async

run_async overloads

set_current_frame_allocator

Set the current frame allocator for this thread.

tag_invoke

tag_invoke overloads

when_all

Execute multiple awaitables concurrently and collect their results.

when_any

when_any overloads

write

Asynchronously write the entire buffer sequence.

+
+
+

Variables

+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

begin

buffer_copy

buffer_empty

buffer_size

end

front

keep_prefix

keep_suffix

prefix

remove_prefix

remove_suffix

sans_prefix

sans_suffix

suffix

+
+
+

Concepts

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

BufferSink

Concept for types that consume buffer data using callee‐owned buffers.

BufferSource

Concept for types that produce buffer data asynchronously.

ConstBufferSequence

Concept for sequences of read‐only buffer regions.

DynamicBuffer

Concept for resizable buffer types with prepare/commit semantics.

DynamicBufferParam

Concept for valid DynamicBuffer parameter passing to coroutines.

ExecutionContext

Concept for types that provide a place where work is executed.

Executor

Concept for types that schedule coroutine execution.

IoAwaitable

Concept for awaitables that participate in the I/O protocol.

IoAwaitableRange

Concept for ranges of full I/O awaitables.

IoRunnable

Concept for task types that can be launched from non‐coroutine contexts.

MatchCondition

Concept for callables that detect delimiters in streamed data.

MutableBufferSequence

Concept for sequences of writable buffer regions.

ReadSource

Concept for types providing complete reads from a data source.

ReadStream

Concept for types providing awaitable read operations.

Stream

Concept for types providing both read and write operations.

WriteSink

Concept for types providing complete writes with EOF signaling.

WriteStream

Concept for types that provide awaitable write operations.

awaitable_decomposes_to

Concept for awaitables whose return type decomposes to a specific typelist.

decomposes_to

Concept for types that decompose to a specific typelist.

+
+
+

Deduction Guides

+ +++ + + + + + + + + + + + +

Name

buffer_param<BS>

strand<Ex>

+
+
+
+
+

boost::capy::this_coro namespace

+
+
+

Namespace for coroutine environment accessors.

+
+
+

Types

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

allocator_tag

Tag type for coroutine allocator retrieval.

environment_tag

Tag type for coroutine environment retrieval.

executor_tag

Tag type for coroutine executor retrieval.

stop_token_tag

Tag type for coroutine stop token retrieval.

+
+
+

Variables

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Name

Description

allocator

Tag object that yields the current frame allocator when awaited.

environment

Tag object that yields the current environment when awaited.

executor

Tag object that yields the current executor when awaited.

stop_token

Tag object that yields the current stop token when awaited.

+
+
+
+
+

See Also

+
+
+

io_awaitable_promise_base, io_env

+
+
+

Created with MrDocs

+
+
+
+
+
+
+
+ +
+ + diff --git a/preview/style-guide/index.html b/preview/style-guide/index.html new file mode 100644 index 0000000..fbae29a --- /dev/null +++ b/preview/style-guide/index.html @@ -0,0 +1,1286 @@ + + + + + + + + + + + + + Boostlook Style Guide + + + + + + + + + + + + + + + + +
+
+
+ +

Boostlook Style Guide

+ +
+
+
+

Comprehensive reference of every design token and component in the Boostlook design system. Toggle dark mode to see how all values adapt between themes.

+
+
+
+ + + + +
+

Color Primitives

+
+ +
+

Neutral

+
+
0
#ffffff
+
50
#f5f6f8
+
100
#e4e7ea
+
150
#d5d7d9
+
200
#c7cccf
+
250
#f9f9f9
+
300
#afb3b6
+
400
#949a9e
+
500
#798086
+
600
#62676b
+
700
#494d50
+
750
#1c1c1c
+
800
#393b3f
+
850
#2a2c30
+
900
#18191b
+
950
#0d0e0f
+
+
+ +
+

Brand Orange

+
+
50
#fbf2e6
+
100
#ffeaca
+
200
#ffd897
+
300
#ffc364
+
400
#ffb030
+
500
#ff9f00
+
600
#cd7e00
+
700
#9b5f00
+
800
#694000
+
900
#352000
+
950
#1e1200
+
+
+ +
+

Blue

+
+
0
#f6fafd
+
25
#ebf4f9
+
50
#daeef9
+
100
#c2e2f4
+
200
#92cbe9
+
300
#62b3dd
+
400
#329cd2
+
500
#0284c7
+
600
#026a9f
+
700
#014f77
+
800
#013550
+
850
#01283c
+
900
#001a28
+
950
#000d14
+
+
+ +
+

Positive

+
+
0
#f8fefb
+
50
#f0fef7
+
100
#def7eb
+
200
#bdeed6
+
300
#9ce6c2
+
400
#7bddad
+
500
#5ad599
+
600
#48ac7b
+
700
#36825d
+
800
#255940
+
850
#1c4431
+
900
#132f22
+
950
#0a1b13
+
+
+ +
+

Negative

+
+
50
#fdf1f3
+
100
#ffe6ea
+
200
#ffcad2
+
300
#fe9aab
+
400
#f9677f
+
500
#eb3856
+
600
#bc233c
+
700
#8d1529
+
800
#600d1b
+
900
#39070f
+
950
#1d0408
+
+
+ +
+

Warning

+
+
0
rgba(255,248,243,.5)
+
50
#fff8f3
+
100
#ffefe2
+
200
#ffd4b3
+
300
#feb780
+
400
#ff9442
+
500
#fd760f
+
600
#c25909
+
700
#914104
+
800
#5d2a02
+
900
#341700
+
950
#1f0e01
+
+
+ +
+

Syntax Colors

+

Strong (light mode)

+
+
blue
#1345E8
+
green
#289D30
+
yellow
#A3A38C
+
pink
#D31FA7
+
grey
#9E9E9E
+
+

Weak (dark mode)

+
+
blue
#38DDFF
+
green
#72FE92
+
yellow
#FFF173
+
pink
#F358C0
+
grey
#A3A3A3
+
+
+ +
+

Accent Colors

+

Weak

+
+
teal
#C9F2EE
+
yellow
#F8EBA9
+
green
#E4E4C0
+
+

Strong

+
+
teal
#64DACE
+
yellow
#F5D039
+
green
#CACA62
+
+
+ +
+

Error Colors

+
+
weak
#FDF2F2
+
mid
#FF3B30
+
strong
#D32F2F
+
+
+ +
+
+ +
+ + + + +
+

Semantic Color Tokens

+
+

These tokens map primitives to semantic roles. They automatically switch between light and dark themes.

+ +
+

Text

+ + + + + + + + + +
TokenSwatch
--text-main-text-primary
--text-main-text-body-primary
--text-main-text-body-secondary
--text-main-text-body-tetriary
--text-main-text-body-quaternary
--text-main-text-link-blue
--text-main-text-link-blue-secondary
+
+ +
+

Surface / Background

+ + + + + + + + + +
TokenSwatch
--surface-background-main-base-primary
--surface-background-main-surface-primary
--surface-background-main-surface-secondary
--surface-background-main-surface-tetriary
--surface-background-main-surface-blue-primary
--surface-background-main-surface-blue-secondary
--surface-background-main-surface-blue-tetriary
+
+ +
+

Border

+ + + + + + + + + + + +
TokenSwatch
--border-border-primary
--border-border-secondary
--border-border-tetriary
--border-border-quaternary
--border-border-active
--border-border-blue
--border-border-positive
--border-border-negative
--border-border-warning
+
+ +
+

State Colors

+ + + + + + + + +
TokenSwatch
--text-states-text-positive
--text-states-text-negative
--text-states-text-warning
--text-states-text-additional
--text-states-text-error-strong
--text-states-text-error-mid
+
+ +
+

Code Syntax Tokens

+ + + + + + + + + + + + +
TokenSwatchUse
--text-code-blueKeywords
--text-code-greenStrings, functions
--text-code-yellowNumbers, comments
--text-code-pinkPreprocessor
--text-code-greyComments
--text-code-redOperators
--text-code-purpleKeywords (alt)
--text-code-neutralDefault text
--text-code-navyClasses
--text-code-turquoiseConstants
+
+ +
+
+ +
+ + + + +
+

Typography Scale

+
+ +
+

Font Size Scale

+
+ --typography-font-size-3xs + The quick brown fox (0.625rem) +
+
+ --typography-font-size-2xs + The quick brown fox (0.75rem) +
+
+ --typography-font-size-xs + The quick brown fox (0.875rem) +
+
+ --typography-font-size-sm + The quick brown fox (1rem) +
+
+ --typography-font-size-md + The quick brown fox (1.125rem) +
+
+ --typography-font-size-lg + The quick brown fox (1.25rem) +
+
+ --typography-font-size-xl + The quick brown fox (1.5rem) +
+
+ --typography-font-size-2xl + The quick brown fox (1.75rem) +
+
+ --typography-font-size-3xl + The quick brown fox (2rem) +
+
+ --typography-font-size-4xl + The quick brown fox (2.5rem) +
+
+ --typography-font-size-5xl + The quick brown fox (3rem) +
+
+ +
+

Heading Hierarchy

+

Heading sizes are responsive (mobile vs desktop). Resize the browser to see the shift.

+
+ h1 — --typography-font-size-h1
desktop: 2rem (3xl) / mobile: 1.75rem (2xl)
+ Heading 1 +
+
+ h2 — --typography-font-size-h2
desktop: 1.25rem (lg) / mobile: 1.25rem (lg)
+ Heading 2 +
+
+ h3 — --typography-font-size-h3
desktop: 1.125rem (md) / mobile: 1rem (sm)
+ Heading 3 +
+
+ h4 — --typography-font-size-h4
desktop: 1rem (sm) / mobile: 0.875rem (xs)
+ Heading 4 +
+
+ h5 — --font-size-xs
0.875rem
+ Heading 5 +
+
+ h6 — --font-size-2xs
0.75rem
+ Heading 6 +
+
+ +
+

Font Families

+
+

Noto Sans (body) — The quick brown fox jumps over the lazy dog. 0123456789

+
+
+

Noto Sans Italic — The quick brown fox jumps over the lazy dog. 0123456789

+
+
+

Monaspace Neon (code) — const x = fn(); // 0123456789

+
+
+

Monaspace Xenon (code italic) — // This is a comment

+
+
+ +
+

Font Weight Variations

+

Light (300) — The quick brown fox jumps over the lazy dog.

+

Regular (400) — The quick brown fox jumps over the lazy dog.

+

Medium (500) — The quick brown fox jumps over the lazy dog.

+

Semibold (600) — The quick brown fox jumps over the lazy dog.

+

Bold (700) — The quick brown fox jumps over the lazy dog.

+
+ +
+
+ +
+ + + + +
+

Spacing & Sizing Scale

+
+ +
+ --spacing-size-4xs +
+ 0.125rem / 2px +
+
+ --spacing-size-3xs +
+ 0.25rem / 4px +
+
+ --spacing-size-2xs +
+ 0.5rem / 8px +
+
+ --spacing-size-xs +
+ 0.75rem / 12px +
+
+ --spacing-size-sm +
+ 1rem / 16px +
+
+ --spacing-size-md +
+ 1.125rem / 18px +
+
+ --spacing-size-lg +
+ 1.5rem / 24px +
+
+ --spacing-size-xl +
+ 2rem / 32px +
+
+ --spacing-size-2xl +
+ 2.5rem / 40px +
+
+ --spacing-size-3xl +
+ 3rem / 48px +
+ +
+
+ +
+ + + + +
+

Corner Radius Scale

+
+ +
+

Primitive Radii

+
+
+
+ xs
0.125rem
+
+
+
+ s
0.25rem
+
+
+
+ m
0.375rem
+
+
+
+ l
0.5rem
+
+
+
+ xl
0.75rem
+
+
+
+ xxl
1rem
+
+
+
+ +
+

Responsive Radii (mobile → desktop)

+
+
+
+ --radius-xs +
+
+
+ --radius-s +
+
+
+ --radius-m +
+
+
+ --radius-l +
+
+
+ --radius-xl +
+
+
+ --radius-xxl +
+
+
+ +
+
+ +
+ + + + +
+

Headings

+
+
+

All six heading levels as they appear in documentation pages.

+
+

Heading Level 1

+

Heading Level 2

+

Heading Level 3

+

Heading Level 4

+
Heading Level 5
+
Heading Level 6
+
+
+ +
+ + + + +
+

Paragraphs & Text

+
+
+

This is a standard paragraph of body text. It demonstrates the default font size, line height, and color used across all documentation pages. Good typography makes technical content easier to read and understand.

+
+
+

This paragraph contains bold text, italic text, and bold italic text. It also includes inline code for referencing identifiers like std::vector<int> or function names like co_await within prose.

+
+
+

A shorter paragraph to show spacing between consecutive blocks of text.

+
+
+
+ +
+ + + + +
+ +
+
+

An internal link to another page in this documentation set.

+
+
+

An external link to Boost.org that opens in a new tab.

+
+
+

A same-page anchor link back to the Headings section above.

+
+
+
+ +
+ + + + +
+

Lists

+
+ +
+

Unordered List

+
+
    +
  • +

    First item in the list

    +
  • +
  • +

    Second item with bold and inline code

    +
  • +
  • +

    Third item with a nested list:

    +
    +
      +
    • +

      Nested item A

      +
    • +
    • +

      Nested item B

      +
    • +
    • +

      Nested item C

      +
    • +
    +
    +
  • +
  • +

    Fourth item after the nested list

    +
  • +
+
+
+ +
+

Ordered List

+
+
    +
  1. +

    Clone the repository

    +
  2. +
  3. +

    Install dependencies

    +
  4. +
  5. +

    Build the project:

    +
    +
      +
    1. +

      Run cmake -B build

      +
    2. +
    3. +

      Run cmake --build build

      +
    4. +
    +
    +
  6. +
  7. +

    Run the tests

    +
  8. +
+
+
+ +
+
+ +
+ + + + +
+

Code Blocks

+
+ +
+

highlight.js Code Block

+
+

A C++ code block with highlight.js markup:

+
+
+
+
#include <iostream>
+#include <vector>
+#include <algorithm>
+
+namespace example {
+
+template<typename T>
+class container
+{
+public:
+    /// Constructs an empty container
+    container() = default;
+
+    /// Adds an element to the back
+    void push_back(const T& value)
+    {
+        data_.push_back(value);
+    }
+
+    /// Returns the number of elements
+    [[nodiscard]] size_t size() const noexcept
+    {
+        return data_.size();
+    }
+
+private:
+    std::vector<T> data_;
+};
+
+} // namespace example
+
+int main()
+{
+    example::container<int> c;
+    c.push_back(42);
+    c.push_back(17);
+
+    std::cout << "Size: " << c.size() << "\n";
+    return 0;
+}
+
+
+ +
+

cpp-highlight Code Block

+
+

Markup as produced by the cpp-highlight toolchain:

+
+
+
+
#include <boost/capy/capy.hpp>
+#include <iostream>
+
+namespace capy = boost::capy;
+
+// A simple coroutine that returns an int
+capy::task<int> compute(int x, int y)
+{
+    auto result = co_await capy::async_add(x, y);
+    co_return result * 2;
+}
+
+int main()
+{
+    auto ctx = capy::make_context();
+    auto val = ctx.run(compute(21, 21));
+    std::cout << "Result: " << val << "\n";  // prints 84
+    return 0;
+}
+
+
+
+ +
+

Rouge-style Code Block

+
+

Markup as produced by the Rouge highlighter (Asciidoctor default):

+
+
+
+
#include <string>
+#include <optional>
+
+template<typename T>
+class result
+{
+public:
+    // Construct from a value
+    explicit result(T value)
+        : value_(std::move(value)) {}
+
+    // Construct from an error string
+    explicit result(std::string error)
+        : error_(std::move(error)) {}
+
+    bool has_value() const noexcept
+    {
+        return value_.has_value();
+    }
+
+private:
+    std::optional<T> value_;
+    std::string error_;
+};
+
+
+
+ +
+

Inline Code

+
+

Use std::move() to transfer ownership. The type std::vector<int> is a dynamic array. Call container.size() to get the element count. The keyword co_await suspends a coroutine.

+
+
+ +
+

Short Snippet

+
+
+
task<int> compute_async(int x)
+{
+    auto result = co_await fetch_value(x);
+    co_return result * 2;
+}
+
+
+
+ +
+
+ +
+ + + + +
+

Admonitions

+
+ +
+ + + + + +
+ + +This is a note admonition. Use it for supplementary information that adds context without being critical to the main flow. +
+
+ +
+ + + + + +
+ + +This is a tip admonition. Use it for helpful suggestions, best practices, or shortcuts that improve the reader’s workflow. +
+
+ +
+ + + + + +
+ + +This is a warning admonition. Use it when the reader might encounter unexpected behavior or potential pitfalls. +
+
+ +
+ + + + + +
+ + +This is a caution admonition. Use it for actions that could cause data loss, security issues, or other serious consequences. +
+
+ +
+ + + + + +
+ + +This is an important admonition. Use it for essential information that the reader must not overlook. +
+
+ +
+
+ +
+ + + + +
+

Tables

+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDefaultDescription

buffer_size

std::size_t

4096

The size of the internal read buffer in bytes.

timeout

std::chrono::milliseconds

30000

Maximum time to wait for an operation to complete.

max_retries

int

3

Number of retry attempts before reporting failure.

verbose

bool

false

Enable detailed logging of internal operations.

+
+
+ +
+ + + + +
+

Images & Captions

+
+
+
+Placeholder diagram +
+
Figure 1. Architecture diagram showing the relationship between core components
+
+
+
+ +
+ + + + +
+

Dividers

+
+
+

Content above a horizontal rule.

+
+
+
+

Content below a horizontal rule. The <hr> element provides visual separation between sections.

+
+
+
+ +
+ + + + +
+

Breadcrumbs

+
+
+

Breadcrumbs are visible in the toolbar above the page title. They show the navigation path: Home / Style Guide.

+
+
+
+ +
+ + + + +
+

Page Controls

+
+
+

The prev/next pagination nav appears below, as it would at the bottom of any documentation page.

+
+
+
+ + +
+
+ +
+ + diff --git a/preview/why-capy.html b/preview/why-capy.html new file mode 100644 index 0000000..7e2ee7d --- /dev/null +++ b/preview/why-capy.html @@ -0,0 +1,1016 @@ + + + + + + + + + + + + + + Why Capy? :: Boost Libraries Documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Why Capy?

+
+
+
+

Boost.Asio is currently the world leader in portable asynchronous I/O. The standard is silent here. The global ecosystem offers nothing comparable.

+
+
+

Capy is the first offering which surpasses Boost.Asio in its domain

+
+
+

The sections that follow will demonstrate this claim. Each section examines a domain where Capy innovates—not by reinventing what works, but by solving problems that have remained unsolved.

+
+
+
+
+

Coroutine-Only Stream Concepts

+
+
+

When Asio introduced AsyncReadStream and AsyncWriteStream, it was revolutionary. For the first time, C++ had formal concepts for buffer-oriented I/O. You could write algorithms that worked with any stream—TCP sockets, SSL connections, serial ports—without knowing the concrete type.

+
+
+

But Asio made a pragmatic choice: support every continuation style. Callbacks. Futures. Coroutines. This "universal model" meant the same async operation could complete in any of these ways. Flexibility came at a cost. The implementation had to handle all cases. Optimizations specific to one model were off the table.

+
+
+

Capy makes a different choice. It commits fully to coroutines. This isn’t a limitation—it’s a liberation. When you know the continuation is always a coroutine, you can optimize in ways that hybrid approaches cannot. The frame is always there. The executor context propagates naturally. Cancellation flows downward without ceremony.

+
+
+

No other library in existence offers coroutine-only stream concepts. Capy is the first.

+
+
+

What Capy Offers

+
+
    +
  • +

    ReadStream, WriteStream, Stream — partial I/O (returns what’s available)

    +
  • +
  • +

    ReadSource, WriteSink — complete I/O with EOF signaling

    +
  • +
  • +

    BufferSource, BufferSink — zero-copy callee-owns-buffers pattern

    +
  • +
+
+
+
+

Comparison

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CapyAsiostdWorld

ReadStream

AsyncReadStream*

WriteStream

AsyncWriteStream*

Stream

ReadSource

WriteSink

BufferSource

BufferSink

+
+

*Asio’s concepts are hybrid (callbacks/futures/coroutines), not coroutine-only

+
+
+
+
+
+

Type-Erasing Stream Wrappers

+
+
+

Every C++ developer who has worked with Asio knows the pain. You write a function that accepts a stream. But which stream? tcp::socket? ssl::stream<tcp::socket>? websocket::stream<ssl::stream<tcp::socket>>? Each layer wraps the previous one, and the type grows. Your function signature becomes a template. Your header includes explode. Your compile times suffer. Your error messages become novels.

+
+
+

Asio does offer type-erasure—but at the wrong level. any_executor erases the executor. any_completion_handler erases the callback. These help, but they don’t address the fundamental problem: the stream type itself propagates everywhere.

+
+
+

Why hasn’t anyone type-erased the stream? Because with callbacks and futures, it’s expensive. The completion handler type is part of the stream’s operation signature. Erasing it means virtual calls on the hot path—for every continuation, not just every I/O operation.

+
+
+

Coroutines change this equation. A coroutine’s continuation is always the same thing: a handle to resume. The caller doesn’t need to know what type will resume it. This is structural type-erasure—built into the language. Capy exploits this. Type-erasing a stream costs one virtual call per I/O operation. That’s it. No per-callback overhead. No template instantiation cascades.

+
+
+

Write any_stream& and accept any stream. Your function compiles once. It links anywhere. Your build times drop. Your binaries shrink. Your error messages become readable. And because coroutines are ordinary functions (not templates), you get natural ABI stability. Link against a new stream implementation without recompiling your code.

+
+
+

No other library in the world does this. Boost would be first.

+
+
+

What Capy Offers

+
+
    +
  • +

    any_read_stream, any_write_stream, any_stream — type-erased partial I/O

    +
  • +
  • +

    any_read_source, any_write_sink — type-erased complete I/O

    +
  • +
  • +

    any_buffer_source, any_buffer_sink — type-erased zero-copy

    +
  • +
  • +

    read, write, read_until, push_to, pull_from — algorithms that work with erased or concrete streams

    +
  • +
+
+
+
+

Comparison

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CapyAsiostdWorld

any_read_stream

any_write_stream

any_stream

any_read_source

any_write_sink

any_buffer_source

any_buffer_sink

read

async_read*

write

async_write*

read_until

async_read_until*

push_to

pull_from

+
+

*Asio’s algorithms only support AsyncReadStream and AsyncWriteStream

+
+
+
+
+
+

Buffer Sequences

+
+
+

Asio got buffer sequences right. The concept-driven approach—ConstBufferSequence, MutableBufferSequence—enables scatter/gather I/O without allocation. You can combine buffers from different sources and pass them to a single write call. The operating system handles them as one logical transfer. This is how high-performance networking works.

+
+
+

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 slice, front, consuming_buffers—customization points 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.

+
+
+

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 P1100R0 for the full story.)

+
+
+

Coroutines eliminate this problem entirely. The coroutine frame owns the buffer. There’s no decay-copy. There’s no ownership transfer. The buffer lives in the frame until the coroutine completes. Capy has one DynamicBuffer concept. It works.

+
+
+

One more thing: std::ranges cannot help here. ranges::size returns the number of buffers, not the total bytes. Range views can drop entire elements, but buffer sequences need byte-level trimming. The abstractions don’t match. Buffer sequences need their own concepts.

+
+
+

What Capy Offers

+
+
    +
  • +

    ConstBufferSequence, MutableBufferSequence, DynamicBuffer — core concepts (Asio-compatible)

    +
  • +
  • +

    flat_dynamic_buffer, circular_dynamic_buffer, buffer_pair — additional concrete types

    +
  • +
  • +

    slice, front, buffer_array, consuming_buffers — byte-level manipulation utilities

    +
  • +
+
+
+
+

Comparison

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CapyAsiostdWorld

ConstBufferSequence

ConstBufferSequence

MutableBufferSequence

MutableBufferSequence

DynamicBuffer

DynamicBuffer_v1/v2*

const_buffer

const_buffer

mutable_buffer

mutable_buffer

flat_dynamic_buffer

circular_dynamic_buffer

vector_dynamic_buffer

dynamic_vector_buffer

string_dynamic_buffer

dynamic_string_buffer

buffer_pair

consuming_buffers

slice

front

buffer_array

buffer_copy

buffer_copy

Byte-level trimming

+
+

*Asio has confusing v1/v2 split due to callback composition problems

+
+
+
+
+
+

Coroutine Execution Model

+
+
+

When you write a coroutine, three questions arise immediately. Where does it run? How do you cancel it? How is its frame allocated?

+
+
+

These seem like simple questions. They are not. The answers determine whether your coroutine system is usable in production.

+
+
+

Where does it run? A coroutine needs an executor—something that schedules its resumption. When coroutine A awaits coroutine B, B needs to know A’s executor so completions dispatch to the right place. This context must flow downward through the call chain. Pass it explicitly to every function? Your APIs become cluttered. Query it from the caller’s promise? Your awaitables become tightly coupled to specific promise types.

+
+
+

How do you cancel it? A user clicks Cancel. A timeout expires. The server is shutting down. Your coroutine needs to stop—gracefully, without leaking resources. C++20 gives us std::stop_token, a beautiful one-shot notification mechanism. But how does a nested coroutine receive the token? Pass it explicitly? More API clutter. And what about pending I/O operations—can they be cancelled at the OS level, or do you wait for them to complete naturally?

+
+
+

How is its frame allocated? Coroutine frames live on the heap by default. For high-throughput servers handling thousands of concurrent operations, allocation overhead matters. You want to reuse frames. You want custom allocators. But here’s the catch: the frame is allocated before the coroutine body runs. The allocator can’t be a parameter—parameters live in the frame. How do you pass an allocator to something that allocates before it can receive parameters?

+
+
+

Asio has answers to these questions, but they’re constrained. Asio must support callbacks and futures alongside coroutines. It cannot assume the continuation is always a coroutine. It cannot build an execution model optimized for coroutines alone. And it bundles everything together—execution model, networking, timers, platform abstractions—in one monolithic library.

+
+
+

The standard has std::execution (P2300), the sender/receiver model. It’s powerful and general. It’s also complex, academic, and not designed for coroutines first. It has the "late binding problem"—allocators flow backward, determined at the point of connection rather than at the point of creation. Ergonomic allocator control is difficult. P3552R3 proposes a task type, but it’s built on sender/receiver and inherits its limitations.

+
+
+

Capy takes a different path. It builds an execution model purpose-built for coroutines and I/O.

+
+
+

The IoAwaitable protocol solves context propagation. When you co_await, the caller passes its executor and stop token to the child through an extended await_suspend signature. No explicit parameters. No promise coupling. Context flows forward, naturally.

+
+
+

Stop tokens propagate automatically. Cancel at the top of your coroutine tree, and every nested operation receives the signal. Capy integrates with OS-level cancellation—CancelIoEx on Windows, IORING_OP_ASYNC_CANCEL on Linux. Pending I/O operations cancel immediately.

+
+
+

Frame allocation uses forward flow. The two-call syntax of run_async(executor)(my_task()) sets a thread-local allocator before the task is evaluated. The task’s operator new reads it. No late binding. No backward flow. Ergonomic control over where every frame is allocated.

+
+
+

And Capy separates execution from platform. The execution model—executors, cancellation, allocation—lives in Capy. Platform abstractions—sockets, io_uring, IOCP—live in Corosio. Clean boundaries. Testable components. You can use Capy’s execution model with a different I/O backend if you choose.

+
+
+

Most importantly, Capy defines a taxonomy of awaitables. IoAwaitable is the base protocol for any type that participates in context propagation. IoRunnable refines it with the launch interface needed by run_async and run. This hierarchy means you can write your own task types that integrate with Capy’s execution model. Asio’s awaitable<T> is a concrete type, not a concept. You use it or you don’t. Capy gives you building blocks.

+
+
+

No other solution like this exists. Not Asio. Not std::execution. Not anywhere in the global ecosystem. Capy is the first.

+
+
+

What Capy Offers

+
+
    +
  • +

    IoAwaitable, IoRunnable — taxonomy of awaitable concepts

    +
  • +
  • +

    task<T> — concrete task type implementing the protocol (user-defined tasks also supported)

    +
  • +
  • +

    run, run_async — launch functions with forward-flow allocator control

    +
  • +
  • +

    strand, thread_pool, async_mutex, async_event — concurrency primitives

    +
  • +
  • +

    frame_allocator, recycling_memory_resource — coroutine-optimized allocation

    +
  • +
+
+
+
+

Comparison

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CapyAsiostdWorld

IoAwaitable

IoRunnable

io_awaitable_promise_base

task<T>

awaitable<T>*

P3552R3**

run

run_async

co_spawn*

strand

strand

executor_ref

any_executor

thread_pool

thread_pool

static_thread_pool

execution_context

execution_context

frame_allocator

recycling_memory_resource

async_mutex

async_event

stop_token propagation

stop_token*

User-defined task types

Execution/platform isolation

Forward-flow allocator control

+
+

*Asio’s are not extensible, no concept taxonomy

+
+
+

**P3552R3 is sender/receiver based, has allocator timing issue

+
+
+

***std has the token but no automatic propagation

+
+
+
+
+
+

The Road Ahead

+
+
+

For twenty five years, Boost.Asio has stood alone. It defined what portable asynchronous I/O looks like in C++. No serious competitor offering its depth of offerings has appeared. It defined the promising Networking TS. Asio earned its place through years of production use, careful evolution, and relentless focus on real problems faced by real developers.

+
+
+

Capy builds on Asio’s foundation—the buffer sequences, the executor model, the hard-won lessons about what works. But where Asio must preserve compatibility with over decades of existing code, Capy is free to commit fully to the future. C++20 coroutines are not an afterthought here. They are the foundation.

+
+
+

The result is something new. Stream concepts designed for coroutines alone. Type-erasure at the level where it matters most. A simple execution model discovered through use-case-first design. Clean separation between execution and platform. A taxonomy of awaitables that invites extension rather than mandating a single concrete type.

+
+
+

Meanwhile, the C++ standards committee has produced std::execution—a sender/receiver model of considerable theoretical elegance. It is general. It is powerful. It is also complex, and its relationship to the I/O problems that most C++ developers face daily remains unclear. The community watches, waits, and wonders when the abstractions will connect to the work they need to accomplish.

+
+
+

Boost has always been where the practical meets the principled. Where real-world feedback shapes design. Where code ships before papers standardize. Capy continues this tradition.

+
+
+

If you are reading this as a Boost contributor, know what you are part of. This is the first library to advance beyond Asio in the domains where they overlap. Not by abandoning what works, but by building on it. Not by chasing theoretical purity, but by solving the problems that have frustrated C++ developers for years: template explosion, compile-time costs, error message novels, ergonomic concurrency, and more.

+
+
+

The coroutine era has arrived. And Boost, as it has so many times before, is leading the way.

+
+
+
+ + +
+
+ +
+ +