diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4a3a4578a..df6a5f1a8 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -138,7 +138,12 @@ jobs: cd boost-root/libs/capy cd doc - bash ./build_antora.sh + # Tee'd purely to keep the build log readable in the step output; + # Antora exits zero even on failure, which is why the checks below + # exist. The injection gate reads a report file, not this log -- the + # reference extension does not pass MrDocs' stdout through. + set -o pipefail + bash ./build_antora.sh 2>&1 | tee "$RUNNER_TEMP/antora.log" # Antora returns zero even if it fails, so we check if the site directory exists if [ ! -d "build/site" ]; then @@ -146,6 +151,30 @@ jobs: exit 1 fi + + # BLOCKING, but deliberately not a count. A MrDocs without the + # extension installed ignores the script entirely and renders the + # reference with no examples while still reporting success, so something + # has to notice. Checking that one known example reached the HTML catches + # that without asking anyone to maintain a number: this example exists + # only in test/doc/reference/work_guard.record.cpp, never in a header. + - name: Doc-quality - reference examples were injected (BLOCKING) + run: | + set -euo pipefail + site=boost-root/libs/capy/doc/build/site + if ! grep -rqF keep_alive_while_setting_up "$site/capy/reference"; then + echo "No injected example found in the rendered reference." >&2 + echo "The reference-snippets transform did not run, or its output" >&2 + echo "did not reach the HTML. doc/build_antora.sh installs the" >&2 + echo "extension into a MrDocs and exports MRDOCS_ROOT; check that it" >&2 + echo "did, and that the Antora reference extension accepted it -- it" >&2 + echo "logs 'Using local MrDocs' at debug level, and setting a" >&2 + echo "'version' in doc/local-playbook.yml makes it reject a local" >&2 + echo "install and silently download its own instead." >&2 + exit 1 + fi + echo "the rendered reference carries its injected examples" + - name: Create Antora Docs Artifact uses: actions/upload-artifact@v4 with: diff --git a/doc/addons/extensions/reference-snippets.lua b/doc/addons/extensions/reference-snippets.lua new file mode 100644 index 000000000..6cd2f9edd --- /dev/null +++ b/doc/addons/extensions/reference-snippets.lua @@ -0,0 +1,245 @@ +-- Inject compiled reference examples into the MrDocs corpus. +-- +-- Examples live as tagged regions in checked-in .cpp files under +-- test/doc/reference/, compiled by boost_capy_doc_tests like every other +-- snippet. This transform reads those regions and injects them into the +-- matching symbol's documentation, so the reference renders an example the +-- normal build has already compiled. Compilation and injection stay +-- independent: CI compiles the files whether or not the docs build, and the +-- docs build injects them whether or not they compile. +-- +-- The file name IS the mapping: a symbol's examples live in +-- +-- test/doc/reference/..cpp +-- +-- where is the qualified name with `boost::capy::` stripped and `::` +-- replaced by `__`. So boost::capy::work_guard (a record) reads +-- `work_guard.record.cpp`. The kind is part of the name because a name alone +-- is ambiguous: `work_guard` also matches three constructors and their +-- overload set. Where even that is ambiguous, the symbol's unique MrDocs +-- anchor is tried first: `..cpp`. +-- +-- Discovery works symbol-first, opening a predicted path, because MrDocs' Lua +-- sandbox blocks io.popen and Lua has no directory listing. +-- +-- A file may hold several tagged regions; they are injected in file order. +-- Each is placed directly after the "Example" heading that `@par Example` +-- produces, so the rendered order matches what the docstring declares. +-- Without such a heading the block is appended. + +local SOURCE_DEFAULT = "test/doc/reference" +local STRIP_PREFIX = "boost::capy::" +-- Heading title that marks a position without rendering; see the anchor loop. +local SENTINEL = "!example" + +-- Scalar fields copied when rebuilding a block. `sym.doc.document` accepts only +-- plain tables and rejects the userdata proxies it hands out, so appending to a +-- symbol's documentation means deep-copying every existing block first. A field +-- missing from this list is dropped silently, which is why the injection is +-- verified against a no-transform baseline rather than trusted. +-- `level` is deliberately absent: MrDocs' generic setter refuses to write it +-- ("field 'level' has a type the generic setter cannot yet write"), as an +-- integer or a float. Every heading in this corpus is level 1, which is what +-- `@par` produces and what the templates default to, so omitting it round-trips +-- unchanged -- verified by diffing the rendered corpus against a no-transform +-- baseline. A corpus using deeper headings would need this fixed upstream. +local SCALARS = { + "kind", "literal", "lang", "title", "name", "text", + "href", "anchor", "id", "style", "admonition", "admonish", "symbol", "href_text", +} + +-- Child blocks hang off more than one field name: a paragraph uses `children`, +-- a list uses `items` (of `listItem`, which in turn uses `blocks`), and an +-- admonition uses `blocks`. Recursing only `children` silently drops list items +-- and note bodies -- caught by the baseline diff, not by any error. +local CONTAINERS = { "children", "items", "blocks" } + +local function fail(msg) + error("[reference-snippets] " .. msg, 0) +end + +local function copy(node) + local out = {} + for _, f in ipairs(SCALARS) do + local ok, v = pcall(function() return node[f] end) + if ok and v ~= nil and type(v) ~= "userdata" and type(v) ~= "table" then + -- Numbers read back as Lua floats (a heading's level is 1.0), and the + -- generic setter rejects a float where the DOM holds an integer. + if type(v) == "number" and math.tointeger(v) then v = math.tointeger(v) end + out[f] = v + end + end + for _, field in ipairs(CONTAINERS) do + local ok, kids = pcall(function() return node[field] end) + if ok and kids ~= nil then + local c = {} + for _, k in ipairs(kids) do c[#c + 1] = copy(k) end + if #c > 0 then out[field] = c end + end + end + return out +end + +-- The first literal found anywhere under a node, used to identify a heading. +local function text_of(node) + local ok, lit = pcall(function() return node.literal end) + if ok and type(lit) == "string" and lit ~= "" then return lit end + local ok2, kids = pcall(function() return node.children end) + if ok2 and kids then + for _, k in ipairs(kids) do + local t = text_of(k) + if t then return t end + end + end + return nil +end + +local function qualified_name(ctx, sym) + local parts, cur = {}, sym + while cur and cur.name ~= nil do + table.insert(parts, 1, cur.name) + cur = cur.parent and ctx.corpus.get(cur.parent) or nil + end + return table.concat(parts, "::") +end + +local function slug(qname) + local s = qname + if s:sub(1, #STRIP_PREFIX) == STRIP_PREFIX then s = s:sub(#STRIP_PREFIX + 1) end + s = s:gsub("::", "__") + -- Anything not an identifier character collapses to `_`, so a call operator + -- (whose qualified name is literally `operator()`) yields a usable file name. + return (s:gsub("[^%w_]+", "_")) +end + +local function dedent(lines) + local margin + for _, l in ipairs(lines) do + if l:match("%S") then + local n = #(l:match("^[ \t]*")) + if margin == nil or n < margin then margin = n end + end + end + local out = {} + for _, l in ipairs(lines) do out[#out + 1] = l:sub((margin or 0) + 1) end + while #out > 0 and not out[1]:match("%S") do table.remove(out, 1) end + while #out > 0 and not out[#out]:match("%S") do table.remove(out) end + return table.concat(out, "\n") +end + +-- Tagged regions in a file, in order. Returns nil when the file does not exist. +local function read_regions(path) + local f = io.open(path, "r") + if not f then return nil end + local lines = {} + for l in f:lines() do lines[#lines + 1] = l end + f:close() + + local out, open_tag, body = {}, nil, nil + for i, l in ipairs(lines) do + local t = l:match("^%s*//%s*tag::([%w_%-]+)%[%]%s*$") + local e = l:match("^%s*//%s*end::([%w_%-]+)%[%]%s*$") + if t then + if open_tag then fail(path .. ":" .. i .. ": tag '" .. t .. "' opens inside '" .. open_tag .. "'") end + open_tag, body = t, {} + elseif e then + if open_tag ~= e then + fail(path .. ":" .. i .. ": end::" .. e .. "[] does not close the open tag") + end + out[#out + 1] = { tag = open_tag, code = dedent(body) } + open_tag, body = nil, nil + elseif open_tag then + body[#body + 1] = l + end + end + if open_tag then fail(path .. ": tag '" .. open_tag .. "' is never closed") end + if #out == 0 then fail(path .. ": file exists but declares no // tag::name[] region") end + return out +end + +mrdocs.register_transform("reference-snippets", function(ctx) + local root = (ctx.params and ctx.params.source) or SOURCE_DEFAULT + local injected, files, missing = 0, 0, {} + + for _, sym in ipairs(ctx.corpus.symbols) do + if sym.name ~= nil and sym.doc then + local doc = sym.doc.document or {} + + -- Anchors are the bare `@par Example` headings, in order, each + -- taking exactly one region. A titled heading such as + -- `@par Mutable Buffer Example` is a section label, not a position: + -- the migration put a bare `@par Example` immediately before every + -- block, so the bare ones mark where the code actually was. Pinning + -- every region to the first anchor would stack them under one title + -- and leave the other sections empty. + -- Each `@par !example ` marker names the region it wants. The + -- marker is consumed rather than rendered, so the example lands where + -- the docstring puts it, and naming the region keeps overloads that + -- share a file independent of the order MrDocs visits them in -- an + -- order that differs between corpora, and that silently swapped two + -- `armed` examples on the published site. + local seq, anchors = {}, {} + for _, b in ipairs(doc) do seq[#seq + 1] = b end + for i, b in ipairs(seq) do + if b.kind == "heading" then + local t = text_of(b) + local tag = t and t:match("^" .. SENTINEL .. "%s+(%S+)$") + if tag then anchors[#anchors + 1] = { at = i, tag = tag } end + end + end + local at = anchors[1] and anchors[1].at or nil + + if at then + local base = root .. "/" .. slug(qualified_name(ctx, sym)) + local path = base .. "." .. tostring(sym.anchor) .. ".cpp" + local regions = read_regions(path) + if not regions then + path = base .. "." .. tostring(sym.kind) .. ".cpp" + regions = read_regions(path) + end + if not regions then + -- Fail-open guard: the docstring promises an example and no + -- file provides one, so the reference would render an empty + -- "Example" section. + missing[#missing + 1] = qualified_name(ctx, sym) .. + " (expected " .. base .. "." .. tostring(sym.kind) .. ".cpp)" + else + files = files + 1 + local blocks + local by_tag = {} + for _, r in ipairs(regions) do by_tag[r.tag] = r end + local picked = {} + for k, a in ipairs(anchors) do + local r = by_tag[a.tag] + if not r then + fail(string.format("%s has no region tagged '%s', named by %s", + path, a.tag, qualified_name(ctx, sym))) + end + picked[k] = r + end + + -- Rebuild, replacing each marker with the region it names. + local nth, out = 0, {} + for i, b in ipairs(seq) do + if anchors[nth + 1] and anchors[nth + 1].at == i then + nth = nth + 1 + out[#out + 1] = { kind = "code", literal = picked[nth].code } + injected = injected + 1 + else + out[#out + 1] = copy(b) + end + end + blocks = out + sym.doc.document = blocks + end + end + end + end + + if #missing > 0 then + fail("these symbols document an @par Example with no snippet file:\n " .. + table.concat(missing, "\n ")) + end + print(string.format("[reference-snippets] injected %d example(s) from %d file(s) under %s", + injected, files, root)) +end) diff --git a/doc/build_antora.sh b/doc/build_antora.sh index 14251113c..277e485a0 100755 --- a/doc/build_antora.sh +++ b/doc/build_antora.sh @@ -21,6 +21,57 @@ echo "Building documentation with Antora..." echo "Installing npm dependencies..." npm ci +# The reference examples are injected by addons/extensions/reference-snippets.lua. +# MrDocs loads extensions only from /share/mrdocs/addons/extensions, and +# its `addons-supplemental` config key is recognised but has no effect, so the +# extension has to be placed inside a MrDocs install. Doing it here rather than in +# CI means every caller gets it: this repository's docs workflow, the C++ Alliance +# doc build, and a plain local run. Without it the reference builds with no +# examples at all and reports success. +# +# develop-release rather than a tagged release: MrDocs' extension API postdates +# v0.8.0. The tag is rolling, so this URL always names the current develop build +# and needs no API call or token. +if [ -z "${MRDOCS_ROOT:-}" ]; then + case "$(uname -s)" in + Linux) mrdocs_asset="MrDocs-develop-Linux.tar.gz" ;; + Darwin) mrdocs_asset="MrDocs-develop-Darwin.tar.gz" ;; + *) echo "No MrDocs build for $(uname -s); set MRDOCS_ROOT to an install." >&2 + exit 1 ;; + esac + mrdocs_dir="$(pwd)/build/mrdocs" + if ! find "$mrdocs_dir" -type f -name mrdocs -perm -u+x 2>/dev/null | grep -q .; then + echo "Fetching MrDocs ($mrdocs_asset)" + mkdir -p "$mrdocs_dir" + curl -fsSL --retry 3 --retry-delay 2 \ + "https://github.com/cppalliance/mrdocs/releases/download/develop-release/$mrdocs_asset" \ + -o "$mrdocs_dir/mrdocs.tar.gz" + tar -xzf "$mrdocs_dir/mrdocs.tar.gz" -C "$mrdocs_dir" + rm -f "$mrdocs_dir/mrdocs.tar.gz" + fi + mrdocs_bin=$(find "$mrdocs_dir" -type f -name mrdocs -perm -u+x | head -n 1) + if [ -z "$mrdocs_bin" ]; then + echo "MrDocs binary not found under $mrdocs_dir" >&2 + exit 1 + fi + MRDOCS_ROOT=$(dirname "$(dirname "$mrdocs_bin")") + export MRDOCS_ROOT +fi + +# Install the extension into whichever MrDocs will be used, including one the +# caller supplied. +mkdir -p "$MRDOCS_ROOT/share/mrdocs/addons/extensions" +cp addons/extensions/*.lua "$MRDOCS_ROOT/share/mrdocs/addons/extensions/" +echo "MrDocs: $MRDOCS_ROOT (reference-snippets extension installed)" + +# Later CI steps run in their own shells, so the export above does not reach +# them. lint/mrdocs-warnings.mjs looks for MRDOCS_ROOT; it used to find MrDocs in +# the reference-collector cache, which is no longer populated now that the +# collector is handed an install instead of downloading one. +if [ -n "${GITHUB_ENV:-}" ]; then + echo "MRDOCS_ROOT=$MRDOCS_ROOT" >> "$GITHUB_ENV" +fi + echo "Building docs in custom dir..." PATH="$(pwd)/node_modules/.bin:${PATH}" export PATH diff --git a/doc/local-playbook.yml b/doc/local-playbook.yml index 76ff7ec6d..bd2bee089 100644 --- a/doc/local-playbook.yml +++ b/doc/local-playbook.yml @@ -30,6 +30,17 @@ antora: using-namespaces: - 'boost::' - require: '@cppalliance/antora-cpp-reference-extension' + # Deliberately NO `version` key. The reference examples are injected by + # doc/addons/extensions/reference-snippets.lua, which needs MrDocs' + # extension API -- not in any tagged release (corpus transforms shipped in + # cppalliance/mrdocs#1196, script generators in #1218, both after v0.8.0). + # The docs workflow therefore installs a develop build with that extension + # copied in and points here via MRDOCS_ROOT, which is the real pin. + # + # Setting `version` DEFEATS that: a local install reports its version as + # `0.8.0+`, which can never satisfy "develop", so the extension + # rejects MRDOCS_ROOT and downloads its own copy -- one without the + # extension, which then renders the reference with no examples at all. dependencies: - name: 'boost' repo: 'https://github.com/boostorg/boost.git' diff --git a/doc/mrdocs.yml b/doc/mrdocs.yml index cc3020896..ef518c8ca 100644 --- a/doc/mrdocs.yml +++ b/doc/mrdocs.yml @@ -35,11 +35,14 @@ exclude-symbols: implementation-defined: - 'boost::capy::detail' - 'boost::capy::*::detail' -inaccessible-members: never -inaccessible-bases: never +# `inaccessible-members`/`inaccessible-bases` are gone on develop, which is the +# channel the docs are pinned to (see doc/local-playbook.yml). Their job is done +# by the extract-private* defaults: verified that state_, has_ep_, dummy_, arr_ +# and ep_ appear nowhere in the generated corpus without them. -# Generator -generate: adoc +# Generator. Spelled `generator` since develop; the Antora reference extension +# passes --generator=adoc explicitly in any case. +generator: adoc base-url: https://www.github.com/cppalliance/capy/blob/develop/ # Style @@ -66,6 +69,13 @@ warn-if-doc-error: true # include/boost/capy/ex/run.hpp -- "run: Documented parameter 'alloc' # does not exist" +# Reference examples are injected by addons/extensions/reference-snippets.lua. +# MrDocs loads extensions from /share/mrdocs/addons/extensions, so the +# doc build installs it there (see .github/workflows/docs.yml). Setting +# `addons-supplemental` here does NOT work: the key is recognised but only the +# command-line flag reaches extension discovery, and the Antora extension does +# not expose one. + # Automation auto-function-metadata: false diff --git a/include/boost/capy/buffers.hpp b/include/boost/capy/buffers.hpp index 36f999734..8c5385b8c 100644 --- a/include/boost/capy/buffers.hpp +++ b/include/boost/capy/buffers.hpp @@ -380,10 +380,8 @@ constexpr struct @return The sum of the sizes of all buffers in `bs`. @par Example - @code - std::array bufs = { ... }; - std::size_t total = buffer_size( bufs ); // sum of both sizes - @endcode + @par !example example + */ template constexpr std::size_t operator()( diff --git a/include/boost/capy/buffers/buffer_param.hpp b/include/boost/capy/buffers/buffer_param.hpp index ebe3ae812..2deefbf0b 100644 --- a/include/boost/capy/buffers/buffer_param.hpp +++ b/include/boost/capy/buffers/buffer_param.hpp @@ -50,10 +50,8 @@ namespace capy { When used in coroutine APIs, the outer template function MUST accept the buffer sequence parameter BY VALUE: - @code - task<> write(ConstBufferSequence auto buffers); // CORRECT - task<> write(ConstBufferSequence auto& buffers); // WRONG - dangling reference - @endcode + @par !example example_1 + Pass-by-value ensures the buffer sequence is copied into the coroutine frame and remains valid across suspension @@ -76,20 +74,8 @@ namespace capy { processing some bytes, call `consume()` to advance through the sequence. - @code - 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); - } - } - @endcode + @par !example example_2 + @par Virtual Interface Pattern @@ -102,31 +88,8 @@ namespace capy { `write_impl`'s `span` parameter. Use @ref const_buffer_param to force `const_buffer` storage regardless of what `BS` is: - @code - class base - { - public: - template - task<> write(BS buffers) - { - const_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); - } - } + @par !example example_3 - protected: - virtual task<> write_impl( - std::span buffers, - std::size_t& bytes_written) = 0; - }; - @endcode @tparam BS The buffer sequence type. Must satisfy either ConstBufferSequence or MutableBufferSequence. diff --git a/include/boost/capy/buffers/buffer_slice.hpp b/include/boost/capy/buffers/buffer_slice.hpp index 71e9f6d46..2ce1b0d10 100644 --- a/include/boost/capy/buffers/buffer_slice.hpp +++ b/include/boost/capy/buffers/buffer_slice.hpp @@ -60,10 +60,8 @@ using slice_type = std::conditional_t< concept as `seq` (mutable if `seq` is mutable). @par Example - @code - co_await write(sock, buffer_slice(bufs, 0, 16384)); // first 16 KB - auto rest = buffer_slice(bufs, n); // drop first n - @endcode + @par !example example + @see slice_type, consuming_buffers */ diff --git a/include/boost/capy/buffers/consuming_buffers.hpp b/include/boost/capy/buffers/consuming_buffers.hpp index 509bf85ca..00ebd5040 100644 --- a/include/boost/capy/buffers/consuming_buffers.hpp +++ b/include/boost/capy/buffers/consuming_buffers.hpp @@ -35,17 +35,8 @@ namespace capy { cursor is a local of a composed operation that took its buffers by value. @par Example - @code - consuming_buffers consuming(buffers); - std::size_t total = 0, want = buffer_size(buffers); - while (total < want) - { - auto [ec, n] = co_await stream.read_some(consuming.data()); - consuming.consume(n); - total += n; - if (ec && total < want) co_return {ec, total}; - } - @endcode + @par !example example + @see buffer_slice, slice_of */ diff --git a/include/boost/capy/concept/buffer_archetype.hpp b/include/boost/capy/concept/buffer_archetype.hpp index 7517f0426..e3b5f36cf 100644 --- a/include/boost/capy/concept/buffer_archetype.hpp +++ b/include/boost/capy/concept/buffer_archetype.hpp @@ -25,14 +25,8 @@ namespace capy { accepts any ConstBufferSequence. @par Example - @code - template - concept MyWritable = - requires(T& stream, const_buffer_archetype buffers) - { - stream.write(buffers); - }; - @endcode + @par !example example + */ struct const_buffer_archetype_ { @@ -90,14 +84,8 @@ using const_buffer_archetype = const_buffer_archetype_; accepts any MutableBufferSequence. @par Example - @code - template - concept MyReadable = - requires(T& stream, mutable_buffer_archetype buffers) - { - stream.read(buffers); - }; - @endcode + @par !example example + */ struct mutable_buffer_archetype_ { diff --git a/include/boost/capy/concept/decomposes_to.hpp b/include/boost/capy/concept/decomposes_to.hpp index b1e86398c..911b03638 100644 --- a/include/boost/capy/concept/decomposes_to.hpp +++ b/include/boost/capy/concept/decomposes_to.hpp @@ -135,12 +135,8 @@ using awaitable_return_t = decltype( @tparam Types The expected element types after decomposition. @par Example - @code - struct result { int a; double b; }; + @par !example example - static_assert(decomposes_to); - static_assert(decomposes_to, int, double>); - @endcode */ template concept decomposes_to = requires(T&& t) { @@ -161,19 +157,8 @@ concept decomposes_to = requires(T&& t) { @li The return type of `await_resume()` must decompose to `Types...` @par Example - @code - // Constrain a function to accept only awaitables that return - // a decomposable result of (error_code, size_t) - template - requires awaitable_decomposes_to - task process(A&& op) - { - auto [ec, n] = co_await std::forward(op); - if (ec) - co_return; - // process n bytes... - } - @endcode + @par !example example + */ template concept awaitable_decomposes_to = requires { diff --git a/include/boost/capy/concept/execution_context.hpp b/include/boost/capy/concept/execution_context.hpp index 4fe784cac..c075e86ec 100644 --- a/include/boost/capy/concept/execution_context.hpp +++ b/include/boost/capy/concept/execution_context.hpp @@ -48,28 +48,16 @@ namespace capy { @par Conforming Signatures - @code - class X : public execution_context - { - public: - using executor_type = // Executor - executor_type get_executor() noexcept; - }; - @endcode + @par !example example_1 + @par Example `post` takes a `continuation&`, which no closure converts to; ordinary callers reach it indirectly through `run_async` or similar combinators: - @code - template - void spawn_work( Ctx& ctx, task<> work ) - { - auto ex = ctx.get_executor(); - run_async(ex)(std::move(work)); // schedules work; runs on ctx - } - @endcode + @par !example example_2 + @see Executor, execution_context */ diff --git a/include/boost/capy/concept/executor.hpp b/include/boost/capy/concept/executor.hpp index 6cae87ea3..21e4cc4bd 100644 --- a/include/boost/capy/concept/executor.hpp +++ b/include/boost/capy/concept/executor.hpp @@ -87,16 +87,8 @@ class execution_context; A conforming implementation might look like: - @code - std::coroutine_handle<> dispatch( - continuation& c ) const - { - if( ctx_.running_in_this_thread() ) - return c.h; // symmetric transfer - post( c ); - return std::noop_coroutine(); - } - @endcode + @par !example example_1 + The `post` operation queues for later execution: @@ -143,22 +135,8 @@ class execution_context; @par Conforming Signatures - @code - class E - { - public: - execution_context& context() const noexcept; - - void on_work_started() const noexcept; - void on_work_finished() const noexcept; + @par !example example_2 - std::coroutine_handle<> dispatch( - continuation& c ) const; - void post( continuation& c ) const; - - bool operator==( E const& ) const noexcept; - }; - @endcode @see ExecutionContext, execution_context */ diff --git a/include/boost/capy/concept/io_awaitable.hpp b/include/boost/capy/concept/io_awaitable.hpp index 835c59480..014dd4279 100644 --- a/include/boost/capy/concept/io_awaitable.hpp +++ b/include/boost/capy/concept/io_awaitable.hpp @@ -78,49 +78,13 @@ namespace capy { compiler to find them on the awaiter type. This concept does not require them. - @code - struct A - { - bool await_ready() const noexcept; - - auto await_suspend( - std::coroutine_handle<> h, - io_env const* env ); + @par !example example_1 - T await_resume(); - }; - @endcode @par Example - @code - struct my_io_op - { - io_env const* env_ = nullptr; - continuation cont_; - - auto await_suspend( - std::coroutine_handle<> h, - io_env const* env ) - { - env_ = env; - cont_ = continuation{h}; - // Pass members by value; capturing this - // risks use-after-free in async callbacks. - // When the async operation completes, resume - // via executor.post(cont_) or executor.dispatch(cont_) - // rather than calling h.resume() directly. - start_async( - env_->stop_token, - env_->executor, - cont_ ); - return std::noop_coroutine(); - } - - bool await_ready() const noexcept { return false; } - void await_resume() {} - }; - @endcode + @par !example example_2 + @see IoRunnable */ diff --git a/include/boost/capy/concept/io_runnable.hpp b/include/boost/capy/concept/io_runnable.hpp index cb56b51b5..661847b70 100644 --- a/include/boost/capy/concept/io_runnable.hpp +++ b/include/boost/capy/concept/io_runnable.hpp @@ -81,22 +81,8 @@ namespace capy { @par Conforming Signatures - @code - 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 handle() const noexcept; - void release() noexcept; - }; - @endcode + @par !example example + @see IoAwaitable, run, run_async */ diff --git a/include/boost/capy/concept/read_stream.hpp b/include/boost/capy/concept/read_stream.hpp index 2cdf5267e..1b8b02d70 100644 --- a/include/boost/capy/concept/read_stream.hpp +++ b/include/boost/capy/concept/read_stream.hpp @@ -80,10 +80,8 @@ namespace capy { remains valid until the `co_await` expression returns. @par Conforming Signatures - @code - template< MutableBufferSequence MB > - IoAwaitable auto read_some( MB buffers ); - @endcode + @par !example example_1 + @warning **Pass buffer sequences by value.** A by-value parameter is copied into the coroutine frame, or into the awaitable's state. @@ -101,21 +99,8 @@ namespace capy { copies in O(1). See `doc/buffers-passing-rationale.md`. @par Example - @code - 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 ) ); - total += n; - if( ec ) - co_return; - } - } - @endcode + @par !example example_2 + @see IoAwaitable, MutableBufferSequence, awaitable_decomposes_to */ diff --git a/include/boost/capy/concept/stream.hpp b/include/boost/capy/concept/stream.hpp index 571f42d8d..43526020d 100644 --- a/include/boost/capy/concept/stream.hpp +++ b/include/boost/capy/concept/stream.hpp @@ -33,29 +33,8 @@ namespace capy { `write_some` operations. @par Example - @code - template - task<> echo(S& stream) - { - char buf[1024]; - auto [ec, n] = co_await stream.read_some(make_buffer(buf)); - if(ec) - co_return; + @par !example example - // write_some may transfer fewer than n bytes (the partial-write - // contract it inherits from WriteStream), so loop until every - // byte read is written, or an error stops the loop early. - std::size_t total = 0; - while(total < n) - { - auto [ec2, n2] = co_await stream.write_some( - const_buffer(buf + total, n - total)); - total += n2; - if(ec2) - co_return; - } - } - @endcode @see ReadStream, WriteStream */ diff --git a/include/boost/capy/concept/write_stream.hpp b/include/boost/capy/concept/write_stream.hpp index 7d326f04f..97b9554b0 100644 --- a/include/boost/capy/concept/write_stream.hpp +++ b/include/boost/capy/concept/write_stream.hpp @@ -88,10 +88,8 @@ namespace capy { @par Conforming Signatures - @code - template< ConstBufferSequence Buffers > - IoAwaitable auto write_some( Buffers buffers ); - @endcode + @par !example example_1 + @warning **Pass buffer sequences by value.** A by-value parameter is copied into the coroutine frame, or into the awaitable's state. @@ -110,21 +108,8 @@ namespace capy { @par Example - @code - 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 ) ); - total += n; - if( ec ) - co_return; - } - } - @endcode + @par !example example_2 + @see IoAwaitable, ConstBufferSequence, awaitable_decomposes_to */ diff --git a/include/boost/capy/cond.hpp b/include/boost/capy/cond.hpp index d542f0c04..a814f6aaa 100644 --- a/include/boost/capy/cond.hpp +++ b/include/boost/capy/cond.hpp @@ -26,21 +26,8 @@ namespace capy { @par Example - @code - 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 - } - @endcode + @par !example example + @see error */ diff --git a/include/boost/capy/ex/any_executor.hpp b/include/boost/capy/ex/any_executor.hpp index bde7539f5..28b2a8c36 100644 --- a/include/boost/capy/ex/any_executor.hpp +++ b/include/boost/capy/ex/any_executor.hpp @@ -72,14 +72,8 @@ struct is_strand_type> : std::true_type {}; anywhere a concrete executor is expected. @par Example - @code - any_executor exec = ctx.get_executor(); - if(exec) - { - auto& context = exec.context(); - exec.post(my_coroutine); - } - @endcode + @par !example example + @see executor_ref, Executor */ diff --git a/include/boost/capy/ex/async_event.hpp b/include/boost/capy/ex/async_event.hpp index 241a6ee4d..d0fb7a2bd 100644 --- a/include/boost/capy/ex/async_event.hpp +++ b/include/boost/capy/ex/async_event.hpp @@ -81,21 +81,8 @@ namespace capy { waiters hold intrusive pointers into the event's internal list. @par Example - @code - async_event event; - - task<> waiter() { - auto [ec] = co_await event.wait(); - if(ec) - co_return; - // ... event was set ... - } + @par !example example - task<> notifier() { - // ... do some work ... - event.set(); // Wake all waiters - } - @endcode */ class async_event { diff --git a/include/boost/capy/ex/async_mutex.hpp b/include/boost/capy/ex/async_mutex.hpp index b81f783c6..b73d5f861 100644 --- a/include/boost/capy/ex/async_mutex.hpp +++ b/include/boost/capy/ex/async_mutex.hpp @@ -125,26 +125,8 @@ namespace capy { waiters hold intrusive pointers into the mutex's internal list. @par Example - @code - async_mutex cm; - - task<> protected_operation() { - auto [ec] = co_await cm.lock(); - if(ec) - co_return; - // ... critical section ... - cm.unlock(); - } + @par !example example - // Or with RAII: - task<> protected_operation_raii() { - auto [ec, guard] = co_await cm.scoped_lock(); - if(ec) - co_return; - // ... critical section ... - // unlocks automatically - } - @endcode */ class async_mutex { diff --git a/include/boost/capy/ex/async_waker.hpp b/include/boost/capy/ex/async_waker.hpp index f556bc22b..61531a056 100644 --- a/include/boost/capy/ex/async_waker.hpp +++ b/include/boost/capy/ex/async_waker.hpp @@ -100,21 +100,8 @@ namespace capy { waiter holds a pointer into the object. @par Example - @code - async_waker waker; - - // user-provided timing thread - std::thread th([&waker] { - std::this_thread::sleep_for(100ms); - waker.wake(); - }); - - task<> waiter() { - auto [ec] = co_await waker.wait(); - // resumed on the executor after ~100ms - } - // ... th.join() after the pool drains - @endcode + @par !example example + */ class async_waker { diff --git a/include/boost/capy/ex/execution_context.hpp b/include/boost/capy/ex/execution_context.hpp index c6e956309..8cc7e15ee 100644 --- a/include/boost/capy/ex/execution_context.hpp +++ b/include/boost/capy/ex/execution_context.hpp @@ -51,35 +51,8 @@ namespace capy { and must only be called during destruction. @par Example - @code - struct file_service : execution_context::service - { - protected: - void shutdown() override {} - }; + @par !example example - 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(); - ctx.find_service(); // returns posix_file_service* - ctx.find_service(); // also works - @endcode @see service, ExecutionContext */ @@ -138,18 +111,8 @@ class BOOST_CAPY_DECL @li Optionally define `key_type` to enable base-class lookup. @par Example - @code - struct my_service : execution_context::service - { - explicit my_service(execution_context&) {} + @par !example example - protected: - void shutdown() override - { - // Cancel pending operations, release resources - } - }; - @endcode @see execution_context */ diff --git a/include/boost/capy/ex/executor_ref.hpp b/include/boost/capy/ex/executor_ref.hpp index 8339dfcba..7ba625e4e 100644 --- a/include/boost/capy/ex/executor_ref.hpp +++ b/include/boost/capy/ex/executor_ref.hpp @@ -95,16 +95,8 @@ inline constexpr executor_vtable vtable_for = { anywhere a concrete executor is expected. @par Example - @code - void store_executor(executor_ref ex) - { - if(ex) - ex.post(my_continuation); - } + @par !example example - thread_pool ctx; - store_executor(ctx.get_executor()); - @endcode @see any_executor, Executor */ diff --git a/include/boost/capy/ex/frame_alloc_mixin.hpp b/include/boost/capy/ex/frame_alloc_mixin.hpp index 1823d81ee..e4b0d4127 100644 --- a/include/boost/capy/ex/frame_alloc_mixin.hpp +++ b/include/boost/capy/ex/frame_alloc_mixin.hpp @@ -41,19 +41,8 @@ namespace capy { support that `io_awaitable_promise_base` provides. @par Example - @code - struct my_internal_coroutine - { - struct promise_type : frame_alloc_mixin - { - my_internal_coroutine get_return_object(); - std::suspend_always initial_suspend() noexcept; - std::suspend_always final_suspend() noexcept; - void return_void(); - void unhandled_exception() noexcept; - }; - }; - @endcode + @par !example example + @par Thread Safety The allocation fast path uses thread-local storage and requires diff --git a/include/boost/capy/ex/immediate.hpp b/include/boost/capy/ex/immediate.hpp index 88b42aa13..9ffd96c60 100644 --- a/include/boost/capy/ex/immediate.hpp +++ b/include/boost/capy/ex/immediate.hpp @@ -35,38 +35,12 @@ namespace capy { @tparam T The result type to wrap. @par Example - @code - // Wrap a sync operation as an awaitable - immediate get_value() - { - return {42}; - } + @par !example example_1 - task example() - { - int x = co_await get_value(); // No suspension, returns 42 - } - @endcode @par Building synchronous I/O operations - @code - struct my_sync_sink - { - template - immediate> - write(CB buffers) - { - auto n = process_sync(buffers); - return {{std::error_code(), n}}; - } - - immediate> - write_eof() - { - return {{}}; - } - }; - @endcode + @par !example example_2 + @see ready, io_result */ @@ -136,21 +110,8 @@ struct immediate with no error and the provided values. @par Example - @code - immediate> - write(const_buffer buf) - { - auto n = write_sync(buf); - return ready(n); // success with n bytes - } + @par !example example_1 - immediate> - connect() - { - connect_sync(); - return ready(); // void success - } - @endcode @return An immediate awaitable containing a successful io_result. @@ -211,16 +172,8 @@ ready(T1 t1, T2 t2, T3 t3) with an error code. @par Example - @code - immediate> - write(const_buffer buf) - { - auto ec = write_sync(buf); - if(ec) - return ready(ec, std::size_t{0}); - return ready(buffer_size(buf)); - } - @endcode + @par !example example_2 + @param ec The error code. diff --git a/include/boost/capy/ex/io_awaitable_promise_base.hpp b/include/boost/capy/ex/io_awaitable_promise_base.hpp index abfafa738..216d3f30b 100644 --- a/include/boost/capy/ex/io_awaitable_promise_base.hpp +++ b/include/boost/capy/ex/io_awaitable_promise_base.hpp @@ -46,49 +46,16 @@ namespace capy { For coroutines that need to access their execution environment: - @code - struct my_task - { - struct promise_type : io_awaitable_promise_base - { - my_task get_return_object(); - std::suspend_always initial_suspend() noexcept; - std::suspend_always final_suspend() noexcept; - void return_void(); - void unhandled_exception(); - }; + @par !example example_1 - // ... awaitable interface ... - }; - - my_task example() - { - auto env = co_await this_coro::environment; - // Access env->executor, env->stop_token, env->frame_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::frame_allocator; - } - @endcode @par Custom Awaitable Transformation If your promise needs to transform awaitables (e.g., for affinity or logging), override `transform_awaitable` instead of `await_transform`: - @code - struct promise_type : io_awaitable_promise_base - { - template - auto transform_awaitable(A&& a) - { - // Your custom transformation logic - return std::forward(a); - } - }; - @endcode + @par !example example_2 + The mixin's `await_transform` intercepts @ref this_coro::environment_tag and the fine-grained tag types (@ref this_coro::executor_tag, @@ -102,21 +69,8 @@ namespace capy { (satisfying @ref IoAwaitable), implement the `await_suspend` overload on your coroutine return type: - @code - struct my_task - { - struct promise_type : io_awaitable_promise_base { ... }; + @par !example example_3 - std::coroutine_handle 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 ... - } - }; - @endcode @par Thread Safety The environment is stored during `await_suspend` and read during diff --git a/include/boost/capy/ex/recycling_memory_resource.hpp b/include/boost/capy/ex/recycling_memory_resource.hpp index 54ac89fd8..486b792e3 100644 --- a/include/boost/capy/ex/recycling_memory_resource.hpp +++ b/include/boost/capy/ex/recycling_memory_resource.hpp @@ -39,10 +39,8 @@ namespace capy { The global pool uses a mutex for cross-thread access. @par Example - @code - auto* mr = get_recycling_memory_resource(); - run_async(ex, mr)(my_task()); - @endcode + @par !example example + @see get_recycling_memory_resource @see run_async diff --git a/include/boost/capy/ex/run.hpp b/include/boost/capy/ex/run.hpp index 9f21bd6b6..43bc56330 100644 --- a/include/boost/capy/ex/run.hpp +++ b/include/boost/capy/ex/run.hpp @@ -611,9 +611,8 @@ namespace boost::capy { When co_awaited, the task runs on the specified executor. @par Example - @code - co_await run(other_executor)(my_task()); - @endcode + @par !example example_2 + @param ex The executor on which the task should run. @@ -712,10 +711,8 @@ run(Ex ex, std::stop_token st, Alloc alloc) is overridden. @par Example - @code - std::stop_source source; - co_await run(source.get_token())(cancellable_task()); - @endcode + @par !example example_1 + @param st The stop token for cooperative cancellation. diff --git a/include/boost/capy/ex/run_async.hpp b/include/boost/capy/ex/run_async.hpp index 3233ed064..137959555 100644 --- a/include/boost/capy/ex/run_async.hpp +++ b/include/boost/capy/ex/run_async.hpp @@ -373,19 +373,8 @@ make_trampoline(Ex, Handlers, Alloc) C++17-evaluation-order rationale behind this constraint. @par Example - @code - // Correct usage - wrapper is temporary, task is the direct argument - run_async(ex)(my_task()); + @par !example example - // Compiles - copy elision constructs w directly from the prvalue - auto w = run_async(ex); - w(my_task()); // Compile error: operator() requires rvalue - std::move(w)(my_task()); // Compiles: w is now an rvalue - - // Compiles, but WRONG - task frame allocated before run_async runs - auto t = my_task(); - run_async(ex)(std::move(t)); - @endcode @see run_async */ @@ -538,9 +527,8 @@ class [[nodiscard]] run_async_wrapper The wrapper itself should only be used from one thread. @par Example - @code - run_async(ioc.get_executor())(my_task()); - @endcode + @par !example example_1 + @param ex The executor to execute the task on. @@ -576,18 +564,8 @@ run_async(Ex ex) may be invoked from any thread where the executor schedules work. @par Example - @code - // 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()); - @endcode + @par !example example_2 + @param ex The executor to execute the task on. @param h1 The handler to invoke with the result (and optionally exception). @@ -624,17 +602,8 @@ run_async(Ex ex, H1 h1) may be invoked from any thread where the executor schedules work. @par Example - @code - 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()); - @endcode + @par !example example_3 + @param ex The executor to execute the task on. @param h1 The handler to invoke with the result on success. @@ -674,11 +643,8 @@ run_async(Ex ex, H1 h1, H2 h2) The wrapper itself should only be used from one thread. @par Example - @code - std::stop_source source; - run_async(ex, source.get_token())(cancellable_task()); - // Later: source.request_stop(); - @endcode + @par !example example_4 + @param ex The executor to execute the task on. @param st The stop token for cooperative cancellation. diff --git a/include/boost/capy/ex/strand.hpp b/include/boost/capy/ex/strand.hpp index 44523381d..646f79428 100644 --- a/include/boost/capy/ex/strand.hpp +++ b/include/boost/capy/ex/strand.hpp @@ -69,18 +69,8 @@ namespace capy { Shared objects: Safe. @par Example - @code - thread_pool pool(4); - strand strand(pool.get_executor()); // CTAD deduces the executor type - - // Continuations are linked intrusively into the strand's queue, - // so each one must outlive its time there. Storage is typically - // owned by the awaitable or operation state that posted it. - continuation c1{h1}, c2{h2}, c3{h3}; - strand.post(c1); - strand.post(c2); - strand.post(c3); - @endcode + @par !example example + @tparam Ex The type of the underlying executor. Must satisfy the `Executor` concept. diff --git a/include/boost/capy/ex/this_coro.hpp b/include/boost/capy/ex/this_coro.hpp index 31bb306ad..a21562302 100644 --- a/include/boost/capy/ex/this_coro.hpp +++ b/include/boost/capy/ex/this_coro.hpp @@ -24,15 +24,8 @@ namespace capy { `await_transform` to yield the appropriate values without suspending. @par Example - @code - task example() - { - auto* 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::frame_allocator; - } - @endcode + @par !example example + @see io_awaitable_promise_base, io_env */ @@ -90,15 +83,8 @@ struct frame_allocator_tag {}; executor, stop token, and allocator for this coroutine. @par Example - @code - task example() - { - auto* env = co_await this_coro::environment; - // env->executor - the executor this coroutine is bound to - // env->stop_token - the stop token for cancellation - // env->frame_allocator - the frame allocator - } - @endcode + @par !example example + @par Preconditions An `io_env` must have been installed for this coroutine before the tag @@ -124,12 +110,8 @@ inline constexpr environment_tag environment{}; executor this coroutine is bound to. @par Example - @code - task example() - { - executor_ref ex = co_await this_coro::executor; - } - @endcode + @par !example example + @par Preconditions An `io_env` must have been installed for this coroutine before the tag @@ -156,14 +138,8 @@ inline constexpr executor_tag executor{}; token was passed to this coroutine when it was awaited. @par Example - @code - task cancellable_work() - { - auto token = co_await this_coro::stop_token; - if (token.stop_requested()) - co_return; - } - @endcode + @par !example example + @par Preconditions An `io_env` must have been installed for this coroutine before the tag @@ -191,13 +167,8 @@ inline constexpr stop_token_tag stop_token{}; used for coroutine frame allocation. @par Example - @code - task example() - { - auto* alloc = co_await this_coro::frame_allocator; - // alloc is nullptr when using the default allocator - } - @endcode + @par !example example + @par Preconditions An `io_env` must have been installed for this coroutine before the tag diff --git a/include/boost/capy/ex/thread_pool.hpp b/include/boost/capy/ex/thread_pool.hpp index 866791ae6..d0e20afe1 100644 --- a/include/boost/capy/ex/thread_pool.hpp +++ b/include/boost/capy/ex/thread_pool.hpp @@ -34,13 +34,8 @@ namespace capy { @ref stop. Unsafe for construction and destruction. @par Example - @code - thread_pool pool(4); // 4 worker threads - auto ex = pool.get_executor(); - run_async(ex)(some_task()); // start work; tracked so join() waits for it - pool.join(); // wait for outstanding work to complete - // pool destructor stops the pool, discarding any pending work - @endcode + @par !example example + @note `join()` waits only for work that holds outstanding-work counting, which `run_async` (and `make_work_guard`) provide. A bare diff --git a/include/boost/capy/ex/work_guard.hpp b/include/boost/capy/ex/work_guard.hpp index decd5a77f..926327feb 100644 --- a/include/boost/capy/ex/work_guard.hpp +++ b/include/boost/capy/ex/work_guard.hpp @@ -45,19 +45,8 @@ namespace capy { object requires external synchronization. @par Example - @code - thread_pool pool(1); + @par !example work_guard - // Keep the pool from completing while we set things up - auto guard = make_work_guard(pool.get_executor()); - - // ... post work to pool ... - - // Allow the pool to complete when work is done - guard.reset(); - - pool.join(); - @endcode @note The executor is returned by reference, allowing callers to manage the executor's lifetime directly. This is essential in diff --git a/include/boost/capy/io/any_read_stream.hpp b/include/boost/capy/io/any_read_stream.hpp index c10a70680..229055280 100644 --- a/include/boost/capy/io/any_read_stream.hpp +++ b/include/boost/capy/io/any_read_stream.hpp @@ -62,18 +62,8 @@ namespace capy { are undefined behavior. @par Example - @code - // Owning - takes ownership of the stream - any_read_stream owning_stream(socket{ioc}); - - // Reference - wraps without ownership - socket sock(ioc); - any_read_stream ref_stream(&sock); - - char data[1024]; - mutable_buffer buf(data, sizeof(data)); - auto [ec, n] = co_await owning_stream.read_some(buf); - @endcode + @par !example example + @see any_write_stream, any_stream, ReadStream */ diff --git a/include/boost/capy/io/any_stream.hpp b/include/boost/capy/io/any_stream.hpp index b3ff43183..33fb3fcb4 100644 --- a/include/boost/capy/io/any_stream.hpp +++ b/include/boost/capy/io/any_stream.hpp @@ -52,31 +52,8 @@ namespace capy { and one write may be in flight simultaneously. @par Example - @code - void reader(any_read_stream&); - void writer(any_write_stream&); - - // Owning - takes ownership of the stream - any_stream owning_stream(socket{ioc}); - - // Reference - wraps without ownership - socket sock(ioc); - any_stream ref_stream(&sock); - - // Use read_some from the any_read_stream base - char rdata[1024]; - mutable_buffer rbuf(rdata, sizeof(rdata)); - auto [ec1, n1] = co_await owning_stream.read_some(std::span(&rbuf, 1)); - - // Use write_some from the any_write_stream base - char wdata[] = "hello"; - const_buffer wbuf(wdata, sizeof(wdata)); - auto [ec2, n2] = co_await owning_stream.write_some(std::span(&wbuf, 1)); - - // Pass to functions expecting one capability - reader(owning_stream); // Implicit upcast - writer(owning_stream); // Implicit upcast - @endcode + @par !example example + @see any_read_stream, any_write_stream, ReadStream, WriteStream */ diff --git a/include/boost/capy/io/any_write_stream.hpp b/include/boost/capy/io/any_write_stream.hpp index dd23eda15..de9d37f10 100644 --- a/include/boost/capy/io/any_write_stream.hpp +++ b/include/boost/capy/io/any_write_stream.hpp @@ -63,18 +63,8 @@ namespace capy { are undefined behavior. @par Example - @code - // Owning - takes ownership of the stream - any_write_stream owning_stream(socket{ioc}); - - // Reference - wraps without ownership - socket sock(ioc); - any_write_stream ref_stream(&sock); - - char data[] = "hello"; - const_buffer buf(data, sizeof(data)); - auto [ec, n] = co_await owning_stream.write_some(std::span(&buf, 1)); - @endcode + @par !example example + @see any_read_stream, any_stream, WriteStream */ diff --git a/include/boost/capy/io_result.hpp b/include/boost/capy/io_result.hpp index b9578ad57..f434756a6 100644 --- a/include/boost/capy/io_result.hpp +++ b/include/boost/capy/io_result.hpp @@ -30,18 +30,13 @@ namespace capy { tuple assignment. @par Example - @code - auto [ec, n] = co_await s.read_some(buf); - if (ec) { ... } - @endcode + @par !example example_1 + `std::tie` rebinds into existing variables without introducing new bindings: - @code - std::error_code ec; - std::size_t n = 0; - std::tie(ec, n) = co_await s.read_some(buf); - @endcode + @par !example example_2 + @note Whether the payload is meaningful when the error code is set is defined by the operation that produced the result. diff --git a/include/boost/capy/io_task.hpp b/include/boost/capy/io_task.hpp index ba3bfdcb2..d26d150b5 100644 --- a/include/boost/capy/io_task.hpp +++ b/include/boost/capy/io_task.hpp @@ -24,19 +24,8 @@ namespace capy { The tuple converting constructor allows direct `co_return` of error codes: - @code - io_task<> connect_to_server(socket& s, endpoint ep) - { - co_return co_await s.connect(ep); // returns io_result<> - } - - io_task<> require_ready(bool ready) - { - if(!ready) - co_return make_error_code(error::eof); // error_code converts to io_result<> - co_return {}; - } - @endcode + @par !example example + @tparam Ts Additional value types beyond error_code. */ diff --git a/include/boost/capy/read.hpp b/include/boost/capy/read.hpp index f566fbb1e..97a30d396 100644 --- a/include/boost/capy/read.hpp +++ b/include/boost/capy/read.hpp @@ -74,19 +74,8 @@ namespace capy { @par Example - @code - capy::task<> process_message(capy::ReadStream auto& stream) - { - std::vector header(16); // known header size for some protocol - auto [ec, n] = co_await capy::read(stream, capy::make_buffer(header)); - if (ec == capy::cond::eof) - co_return; // Connection closed - if (ec) - throw std::system_error(ec); - - // at this point `header` contains exactly 16 bytes - } - @endcode + @par !example example + @see ReadStream, MutableBufferSequence */ diff --git a/include/boost/capy/read_at_least.hpp b/include/boost/capy/read_at_least.hpp index de84540d2..7e9e7a89b 100644 --- a/include/boost/capy/read_at_least.hpp +++ b/include/boost/capy/read_at_least.hpp @@ -94,19 +94,8 @@ namespace capy { @par Example - @code - capy::task<> fill_buffer(capy::ReadStream auto& stream) - { - std::vector storage(4096); // generous capacity - // Require 16 header bytes; opportunistically take more. - auto [ec, n] = co_await capy::read_at_least( - stream, capy::make_buffer(storage), 16); - if(ec) - throw std::system_error(ec); - - // at least 16 bytes are available; n may be larger - } - @endcode + @par !example example + @see read, ReadStream, MutableBufferSequence */ diff --git a/include/boost/capy/task.hpp b/include/boost/capy/task.hpp index 85ba2f752..774d6b33e 100644 --- a/include/boost/capy/task.hpp +++ b/include/boost/capy/task.hpp @@ -106,21 +106,8 @@ struct task_return_base @par Example - @code - task compute_value() - { - auto [ec, n] = co_await stream.read_some( buf ); - if( ec ) - co_return 0; - co_return process( buf, n ); - } + @par !example example - task<> run_session( tcp_socket sock ) - { - int result = co_await compute_value(); - // ... - } - @endcode @tparam T The result type. Use `task<>` for `task`. diff --git a/include/boost/capy/test/buffer_to_string.hpp b/include/boost/capy/test/buffer_to_string.hpp index 89c026570..1c95039ea 100644 --- a/include/boost/capy/test/buffer_to_string.hpp +++ b/include/boost/capy/test/buffer_to_string.hpp @@ -27,24 +27,8 @@ namespace test { arguments, it concatenates them in order. @par Example - @code - // Single buffer sequence - const_buffer cb( "hello", 5 ); - std::string s = buffer_to_string( cb ); // "hello" + @par !example example - // Multiple buffer sequences (concatenation) - const_buffer b1( "hello", 5 ); - const_buffer b2( " world", 6 ); - std::string s = buffer_to_string( b1, b2 ); // "hello world" - - // With bufgrind splits: each half is itself a buffer sequence, - // so pass it directly -- there is no .data() to unwrap. - bufgrind bg( cb ); - while( bg ) { - auto [b1, b2] = co_await bg.next(); - BOOST_TEST_EQ( buffer_to_string( b1, b2 ), "hello" ); - } - @endcode @param bufs One or more buffer sequences to concatenate. diff --git a/include/boost/capy/test/bufgrind.hpp b/include/boost/capy/test/bufgrind.hpp index 3a92c8176..88a08c3dc 100644 --- a/include/boost/capy/test/bufgrind.hpp +++ b/include/boost/capy/test/bufgrind.hpp @@ -45,46 +45,16 @@ namespace test { Not thread-safe. @par Example - @code - // Test all split points of a buffer - std::string data = "hello world"; - auto cb = make_buffer( data ); - - fuse f; - auto r = f.inert( [&]( fuse& ) -> task<> { - bufgrind bg( cb ); - while( bg ) { - auto [b1, b2] = co_await bg.next(); - // b1 contains first N bytes (as a buffer sequence) - // b2 contains remaining bytes (as a buffer sequence) - // concatenating b1 + b2 equals original - co_await some_async_operation( b1, b2 ); - } - } ); - @endcode + @par !example example_1 + @par Mutable Buffer Example - @code - // Mutable buffers preserve mutability - char data[100]; - mutable_buffer mb( data, sizeof( data ) ); - - bufgrind bg( mb ); - while( bg ) { - auto [b1, b2] = co_await bg.next(); - // b1, b2 yield mutable_buffer when iterated - } - @endcode + @par !example example_2 + @par Step Size Example - @code - // Skip by 10 bytes for faster iteration - bufgrind bg( cb, 10 ); - while( bg ) { - auto [b1, b2] = co_await bg.next(); - // Visits positions 0, 10, 20, ..., and always size - } - @endcode + @par !example example_3 + @see buffer_slice */ diff --git a/include/boost/capy/test/fuse.hpp b/include/boost/capy/test/fuse.hpp index 4291b7307..c50c0ff73 100644 --- a/include/boost/capy/test/fuse.hpp +++ b/include/boost/capy/test/fuse.hpp @@ -72,38 +72,18 @@ namespace test { @par Basic Inline Usage - @code - fuse()([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; + @par !example example_1 - ec = f.maybe_fail(); - if(ec) - return; - }); - @endcode @par Named Fuse with armed() - @code - fuse f; - MyObject obj(f); - auto r = f.armed([&](fuse&) { - obj.do_something(); - }); - @endcode + @par !example example_2 + @par Using inert() for Single-Run Tests - @code - fuse f; - auto r = f.inert([](fuse& f) { - auto ec = f.maybe_fail(); // Always succeeds - if(some_condition) - f.fail(); // Only way to signal failure - }); - @endcode + @par !example example_3 + @par Dependency Injection (Standalone Usage) @@ -112,87 +92,23 @@ namespace test { to classes for dependency injection without affecting normal operation. - @code - class MyService - { - fuse& f_; - public: - explicit MyService(fuse& f) : f_(f) {} - - std::error_code do_work() - { - auto ec = f_.maybe_fail(); // No-op outside armed/inert - if(ec) - return ec; - // ... actual work ... - return {}; - } - }; - - // Production usage - fuse is no-op - fuse f; - MyService svc(f); - svc.do_work(); // maybe_fail() returns {} always + @par !example example_4 - // Test usage - failures are injected - auto r = f.armed([&](fuse&) { - svc.do_work(); // maybe_fail() triggers failures - }); - @endcode @par Custom Error Code - @code - auto custom_ec = make_error_code( - std::errc::operation_canceled); - fuse f(custom_ec); - auto r = f.armed([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; - }); - @endcode + @par !example example_5 + @par Checking the Result - @code - fuse f; - auto r = f([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; - }); + @par !example example_6 - if(!r) - { - std::cerr << "Failure at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode @par Test Framework Integration - @code - fuse f; - auto r = f([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; - }); - - // Boost.Test - BOOST_TEST(r.success); - if(!r) - BOOST_TEST_MESSAGE("Failed at " << r.loc.file_name() - << ":" << r.loc.line()); - - // Catch2 - REQUIRE(r.success); - if(!r) - INFO("Failed at " << r.loc.file_name() - << ":" << r.loc.line()); - @endcode + @par !example example_7 + */ class fuse { @@ -249,21 +165,8 @@ class fuse @par Example - @code - fuse f; - auto r = f([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; - }); + @par !example example - if(!r) - { - std::cerr << "Failure at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode */ struct result { @@ -290,23 +193,8 @@ class fuse @par Example - @code - auto custom_ec = make_error_code( - std::errc::operation_canceled); - fuse f(custom_ec); - - std::error_code captured_ec; - auto r = f([&](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - { - captured_ec = ec; - return; - } - }); + @par !example example_1 - assert(captured_ec == custom_ec); - @endcode @param ec The error code to deliver at failure points. */ @@ -322,21 +210,8 @@ class fuse @par Example - @code - fuse f; - std::error_code captured_ec; + @par !example example_2 - auto r = f([&](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - { - captured_ec = ec; - return; - } - }); - - assert(captured_ec == error::test_failure); - @endcode */ fuse() : fuse(error::test_failure) @@ -358,27 +233,13 @@ class fuse @par Example - @code - fuse f; - auto r = f([](fuse& f) { - // Error code mode: returns the error - auto ec = f.maybe_fail(); - if(ec) - return; - - // Exception mode: throws system_error - ec = f.maybe_fail(); - if(ec) - return; - }); - @endcode + @par !example example_1 + @par Standalone Usage - @code - fuse f; - auto ec = f.maybe_fail(); // Always returns {} (no-op) - @endcode + @par !example example_2 + @param loc The source location of the call site, captured automatically. @@ -420,28 +281,8 @@ class fuse @par Example - @code - fuse f; - auto r = f([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; + @par !example example_1 - // Explicit failure when a condition is not met - if(some_value != expected) - { - f.fail(); - return; - } - }); - - if(!r) - { - std::cerr << "Test failed at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode @param loc The source location of the call site, captured automatically. @@ -464,33 +305,8 @@ class fuse @par Example - @code - fuse f; - auto r = f([](fuse& f) { - try - { - do_something(); - } - catch(...) - { - f.fail(std::current_exception()); - return; - } - }); + @par !example example_2 - if(!r) - { - try - { - if(r.ep) - std::rethrow_exception(r.ep); - } - catch(std::exception const& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - } - @endcode @param ep The exception pointer to capture. @@ -604,25 +420,8 @@ class fuse @par Example - @code - fuse f; - auto r = f.armed([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; + @par !example example_2 - ec = f.maybe_fail(); - if(ec) - return; - }); - - if(!r) - { - std::cerr << "Failure at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode @param fn The test function to invoke. It receives a reference to the fuse and should call @ref maybe_fail @@ -722,25 +521,8 @@ class fuse @par Example - @code - fuse f; - auto r = f.armed([&](fuse&) -> task { - auto ec = f.maybe_fail(); - if(ec) - co_return; - - ec = f.maybe_fail(); - if(ec) - co_return; - }); + @par !example example_3 - if(!r) - { - std::cerr << "Failure at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode @param fn The coroutine test function to invoke. It receives a reference to the fuse and should call @ref maybe_fail @@ -781,25 +563,8 @@ class fuse handler and return it once the run loop is done. @par Example - @code - // Drive each iteration on a fresh io_context. - auto io_runner = [](capy::task<> t) -> std::exception_ptr - { - corosio::io_context ioc; - std::exception_ptr ep; - capy::run_async(ioc.get_executor(), - [](auto&&...){}, - [&ep](std::exception_ptr e){ ep = e; } - )(std::move(t)); - ioc.run(); - return ep; - }; - auto r = f.armed(io_runner, - [&](capy::test::fuse&) -> capy::task<> - { - co_await corosio::timeout(some_op(), 5s); - }); - @endcode + @par !example example_1 + @param run_one A callable invoked with each iteration's task; it runs the task to completion and returns any escaped exception @@ -830,19 +595,8 @@ class fuse @par Example - @code - // These are equivalent: - fuse f; - auto r1 = f.armed([](fuse& f) { ... }); - auto r2 = f([](fuse& f) { ... }); - - // Inline usage: - auto r3 = fuse()([](fuse& f) { - auto ec = f.maybe_fail(); - if(ec) - return; - }); - @endcode + @par !example example + @param fn The test function to run under failure injection. @@ -886,27 +640,8 @@ class fuse @par Example - @code - fuse f; - auto r = f.inert([](fuse& f) { - auto ec = f.maybe_fail(); // Always succeeds - assert(!ec); + @par !example example_1 - // Only way to signal failure: - if(some_condition) - { - f.fail(); - return; - } - }); - - if(!r) - { - std::cerr << "Test failed at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode @param fn The test function to invoke. It receives a reference to the fuse. Calls to @ref maybe_fail @@ -951,27 +686,8 @@ class fuse @par Example - @code - fuse f; - auto r = f.inert([](fuse& f) -> task { - auto ec = f.maybe_fail(); // Always succeeds - assert(!ec); + @par !example example_2 - // Only way to signal failure: - if(some_condition) - { - f.fail(); - co_return; - } - }); - - if(!r) - { - std::cerr << "Test failed at " - << r.loc.file_name() << ":" - << r.loc.line() << "\n"; - } - @endcode @param fn The coroutine test function to invoke. It receives a reference to the fuse. Calls to @ref maybe_fail diff --git a/include/boost/capy/test/read_stream.hpp b/include/boost/capy/test/read_stream.hpp index 881377bb8..c077f5d26 100644 --- a/include/boost/capy/test/read_stream.hpp +++ b/include/boost/capy/test/read_stream.hpp @@ -42,21 +42,8 @@ namespace test { Not thread-safe. @par Example - @code - fuse f; - read_stream rs( f ); - rs.provide( "Hello, " ); - rs.provide( "World!" ); - - auto r = f.armed( [&]( fuse& ) -> task { - char buf[32]; - auto [ec, n] = co_await rs.read_some( - mutable_buffer( buf, sizeof( buf ) ) ); - if( ec ) - co_return; - // buf contains "Hello, World!" - } ); - @endcode + @par !example example + @see fuse, ReadStream */ diff --git a/include/boost/capy/test/run_blocking.hpp b/include/boost/capy/test/run_blocking.hpp index 7e1cec2cf..6c3a1299c 100644 --- a/include/boost/capy/test/run_blocking.hpp +++ b/include/boost/capy/test/run_blocking.hpp @@ -401,9 +401,8 @@ class [[nodiscard]] run_blocking_wrapper rethrown to the caller. @par Example - @code - run_blocking()(my_void_task()); - @endcode + @par !example example_2 + @return A wrapper that accepts a task for blocking execution. @@ -434,10 +433,8 @@ run_blocking() rethrown. @par Example - @code - int result = 0; - run_blocking([&](int v) { result = v; })(compute()); - @endcode + @par !example example_3 + @param h1 Handler invoked with the result on success, and optionally with `std::exception_ptr` on failure. @@ -469,15 +466,8 @@ run_blocking(H1 h1) to `h2`. @par Example - @code - int result = 0; - run_blocking( - [&](int v) { result = v; }, - [](std::exception_ptr ep) { - std::rethrow_exception(ep); - } - )(compute()); - @endcode + @par !example example_1 + @param h1 Handler invoked with the result on success. @param h2 Handler invoked with the exception on failure. diff --git a/include/boost/capy/test/stream.hpp b/include/boost/capy/test/stream.hpp index 54a6f9a40..3b7f5d5c4 100644 --- a/include/boost/capy/test/stream.hpp +++ b/include/boost/capy/test/stream.hpp @@ -60,29 +60,8 @@ namespace test { undefined behavior. @par Example - @code - fuse f; - - auto r = f.armed( [&]( fuse& ) -> task<> { - // Constructed inside the lambda: armed() re-invokes this - // function once per injected failure point, and a stream - // pair constructed outside would carry buffered state - // across those rounds. - auto [a, b] = make_stream_pair( f ); - - auto [ec, n] = co_await a.write_some( - const_buffer( "hello", 5 ) ); - if( ec ) - co_return; - - char buf[32]; - auto [ec2, n2] = co_await b.read_some( - mutable_buffer( buf, sizeof( buf ) ) ); - if( ec2 ) - co_return; - // buf contains "hello" - } ); - @endcode + @par !example example + @see make_stream_pair, fuse */ diff --git a/include/boost/capy/test/write_stream.hpp b/include/boost/capy/test/write_stream.hpp index 5ba1fd9e7..00211fcf0 100644 --- a/include/boost/capy/test/write_stream.hpp +++ b/include/boost/capy/test/write_stream.hpp @@ -44,23 +44,8 @@ namespace test { Not thread-safe. @par Example - @code - fuse f; - - auto r = f.armed( [&]( fuse& ) -> task { - // Constructed inside the lambda: armed() re-invokes this - // function once per injected failure point, and a write_stream - // constructed outside would carry accumulated data across - // those rounds. - write_stream ws( f ); - - auto [ec, n] = co_await ws.write_some( - const_buffer( "Hello", 5 ) ); - if( ec ) - co_return; - // ws.data() returns "Hello" - } ); - @endcode + @par !example example + @see fuse, WriteStream */ diff --git a/include/boost/capy/when_all.hpp b/include/boost/capy/when_all.hpp index c073a95a9..a649fd4c3 100644 --- a/include/boost/capy/when_all.hpp +++ b/include/boost/capy/when_all.hpp @@ -618,18 +618,8 @@ class when_all_homogeneous_launcher all children complete (exception beats error_code). @par Example - @code - task example() - { - std::vector> reads; - for (auto& buf : buffers) - reads.push_back(stream.read_some(buf)); + @par !example example_1 - auto [ec, counts] = co_await when_all(std::move(reads)); - if (ec) { // handle error - } - } - @endcode @see IoAwaitableRange, when_all */ @@ -741,16 +731,8 @@ template all children complete (exception beats error_code). @par Example - @code - task example() - { - std::vector> jobs; - for (int i = 0; i < n; ++i) - jobs.push_back(process(i)); + @par !example example_2 - auto [ec] = co_await when_all(std::move(jobs)); - } - @endcode @see IoAwaitableRange, when_all */ diff --git a/include/boost/capy/when_any.hpp b/include/boost/capy/when_any.hpp index 43832532e..74e2ed2c8 100644 --- a/include/boost/capy/when_any.hpp +++ b/include/boost/capy/when_any.hpp @@ -695,20 +695,8 @@ class when_any_io_homogeneous_launcher exception is rethrown (which child is unspecified). @par Example - @code - task example() - { - std::vector> reads; - for (auto& buf : buffers) - reads.push_back(stream.read_some(buf)); + @par !example example_1 - auto result = co_await when_any(std::move(reads)); - if (result.index() == 1) - { - auto [idx, n] = std::get<1>(result); - } - } - @endcode @see IoAwaitableRange, when_any */ @@ -826,20 +814,8 @@ template that child's exception is rethrown (which child is unspecified). @par Example - @code - task example() - { - std::vector> jobs; - jobs.push_back(background_work_a()); - jobs.push_back(background_work_b()); + @par !example example_2 - auto result = co_await when_any(std::move(jobs)); - if (result.index() == 1) - { - auto winner = std::get<1>(result); - } - } - @endcode @see IoAwaitableRange, when_any */ diff --git a/include/boost/capy/write.hpp b/include/boost/capy/write.hpp index 4699aba30..8ec858065 100644 --- a/include/boost/capy/write.hpp +++ b/include/boost/capy/write.hpp @@ -82,16 +82,8 @@ namespace capy { @par Example - @code - capy::task<> send_response(capy::WriteStream auto& stream, std::string_view body) - { - auto [ec, n] = co_await capy::write(stream, capy::make_buffer(body)); - if (ec) - throw std::system_error(ec); + @par !example example - // All bytes written successfully - } - @endcode @see WriteStream, ConstBufferSequence, IoAwaitable, io_result, cond. */ diff --git a/include/boost/capy/write_at_least.hpp b/include/boost/capy/write_at_least.hpp index 53773d516..b0879ab28 100644 --- a/include/boost/capy/write_at_least.hpp +++ b/include/boost/capy/write_at_least.hpp @@ -92,17 +92,8 @@ namespace capy { @par Example - @code - capy::task<> flush_at_least(capy::WriteStream auto& stream, std::string_view data) - { - auto [ec, n] = co_await capy::write_at_least( - stream, capy::make_buffer(data), 8); - if(ec) - throw std::system_error(ec); + @par !example example - // at least 8 bytes written; n may be larger - } - @endcode @see write, WriteStream, ConstBufferSequence */ diff --git a/test/doc/CMakeLists.txt b/test/doc/CMakeLists.txt index 0f9d68f4f..07b27eceb 100644 --- a/test/doc/CMakeLists.txt +++ b/test/doc/CMakeLists.txt @@ -26,7 +26,13 @@ function(boost_capy_doc_warnings_as_errors target) endfunction() file(GLOB SNIPPETS CONFIGURE_DEPENDS snippets/*.cpp) -set(PFILES ${SNIPPETS} CMakeLists.txt Jamfile) +# Reference examples: injected into the MrDocs reference by +# doc/addons/extensions/reference-snippets.lua, and compiled here so an example +# in the reference is one the build has already checked. Same target as the +# page snippets -- each file keeps its code in an anonymous namespace, so +# independently authored examples that both define example() do not collide. +file(GLOB REFERENCE_SNIPPETS CONFIGURE_DEPENDS reference/*.cpp) +set(PFILES ${SNIPPETS} ${REFERENCE_SNIPPETS} CMakeLists.txt Jamfile) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "" FILES ${PFILES}) add_executable(boost_capy_doc_tests ${PFILES}) diff --git a/test/doc/Jamfile b/test/doc/Jamfile index 76174cc47..e4ec77fe0 100644 --- a/test/doc/Jamfile +++ b/test/doc/Jamfile @@ -18,7 +18,9 @@ project on ; -run [ glob snippets/*.cpp ] +# reference/*.cpp holds the examples MrDocs injects into the reference; they are +# compiled here so the b2 legs check them too, not just the CMake ones. +run [ glob snippets/*.cpp ] [ glob reference/*.cpp ] ../../extra/test_suite/test_main.cpp ../../extra/test_suite/test_suite.cpp : : : ../../extra/test_suite diff --git a/test/doc/reference/ExecutionContext.concept.cpp b/test/doc/reference/ExecutionContext.concept.cpp new file mode 100644 index 000000000..ed4c7e70e --- /dev/null +++ b/test/doc/reference/ExecutionContext.concept.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::ExecutionContext, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/execution_context.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +class X : public execution_context +{ +public: + using executor_type = executor_ref; // any type satisfying Executor + executor_type get_executor() noexcept; +}; + +static_assert( ExecutionContext ); +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +template +void spawn_work( Ctx& ctx, task<> work ) +{ + auto ex = ctx.get_executor(); + run_async(ex)(std::move(work)); // schedules work; runs on ctx +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/Executor.concept.cpp b/test/doc/reference/Executor.concept.cpp new file mode 100644 index 000000000..05569d138 --- /dev/null +++ b/test/doc/reference/Executor.concept.cpp @@ -0,0 +1,115 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::Executor, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/executor.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +class E +{ + execution_context& ctx_; + std::thread::id home_ = std::this_thread::get_id(); + +public: + explicit E(execution_context& ctx) noexcept : ctx_(ctx) {} + + execution_context& context() const noexcept { return ctx_; } + void on_work_started() const noexcept {} + void on_work_finished() const noexcept {} + + bool operator==(E const& other) const noexcept + { + return &ctx_ == &other.ctx_; + } + + std::coroutine_handle<> dispatch( + continuation& c ) const + { + if( std::this_thread::get_id() == home_ ) + return c.h; // symmetric transfer + post( c ); + return std::noop_coroutine(); + } + + void post( continuation& ) const + { + // enqueue for later execution on this executor's context + } +}; + +static_assert( Executor ); +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +class E +{ +public: + execution_context& context() const noexcept; + + void on_work_started() const noexcept; + void on_work_finished() const noexcept; + + std::coroutine_handle<> dispatch( + continuation& c ) const; + void post( continuation& c ) const; + + bool operator==( E const& ) const noexcept; +}; +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/IoAwaitable.concept.cpp b/test/doc/reference/IoAwaitable.concept.cpp new file mode 100644 index 000000000..6a7cf869e --- /dev/null +++ b/test/doc/reference/IoAwaitable.concept.cpp @@ -0,0 +1,109 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::IoAwaitable, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/io_awaitable.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +struct A +{ + bool await_ready() const noexcept; + + auto await_suspend( + std::coroutine_handle<> h, + io_env const* env ); + + auto await_resume(); +}; +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +struct my_io_op +{ + io_env const* env_ = nullptr; + continuation cont_; + + // Stands in for a real asynchronous entry point (a socket read, a + // timer, ...) that takes its own stop token and executor and + // resumes the continuation from an async callback once the + // operation completes. + void start_async(std::stop_token, any_executor, continuation&) {} + + auto await_suspend( + std::coroutine_handle<> h, + io_env const* env ) + { + env_ = env; + cont_ = continuation{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; } + io_result await_resume() { return {}; } +}; + +static_assert( IoAwaitable ); +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/IoRunnable.concept.cpp b/test/doc/reference/IoRunnable.concept.cpp new file mode 100644 index 000000000..b13f09060 --- /dev/null +++ b/test/doc/reference/IoRunnable.concept.cpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::IoRunnable, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/io_runnable.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +class T +{ +public: + struct promise_type + { + std::exception_ptr exception() noexcept; + int result(); // non-void tasks only + void set_continuation(std::coroutine_handle<>) noexcept; + void set_environment(io_env const*) noexcept; + }; + + std::coroutine_handle handle() const noexcept; + void release() noexcept; +}; +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/README.md b/test/doc/reference/README.md new file mode 100644 index 000000000..259f71767 --- /dev/null +++ b/test/doc/reference/README.md @@ -0,0 +1,101 @@ +# Reference examples + +The examples shown in the MrDocs reference live here, as ordinary C++ compiled by +`boost_capy_doc_tests` alongside the page snippets in `test/doc/snippets/`. An +example in the reference is therefore one the build has already checked. + +Compilation and rendering are independent. CI compiles these files whether or +not the docs build; the docs build injects them whether or not they compile. +Neither waits on the other, and MrDocs stays a dependency of the docs workflow +only. + +## Adding an example + +1. Write the example in the file named after the symbol that documents it: + + ```text + test/doc/reference/..cpp + ``` + + `` is the symbol's qualified name with `boost::capy::` stripped and + `::` replaced by `__`; `` is what MrDocs calls it (`record`, + `function`, `namespace`, `concept`, `typedef`, `variable`, `enum`). So + `boost::capy::work_guard`, a class, is `work_guard.record.cpp`, and + `boost::capy::test::fuse` is `test__fuse.record.cpp`. The name *is* the + mapping: the transform opens that path, because MrDocs' Lua sandbox has no + directory listing. + +2. Put the code the reference should show inside a tagged region: + + ```cpp + namespace ex_1 { + // tag::example[] + void keep_alive_while_setting_up() + { + ... + } + // end::example[] + } // namespace ex_1 + ``` + + Only what is between the tags renders. Includes, warning suppressions and + the namespaces stay outside them, so the reader sees the example and not the + scaffolding. Each region gets its own namespace inside a file-level + anonymous one: ten examples across the library define `example()`, and this + is what keeps them from colliding with each other or across files. + +3. Add `@par Example` to the docstring where the example belongs: + + ```text + @par Example + ``` + + The transform inserts the code directly after that heading, which is how the + example lands where the docstring says rather than at the bottom. A docstring + with `@par Example` and no example, and no file to supply one, fails the docs + build. + +## Several examples for one symbol + +Add more tagged regions to the same file, each in its own namespace. They are +injected in file order. + +## Symbols that share a file + +Overload sets and duplicated records can share a `.` name. Give +each region a declaration naming the symbols it belongs to: + +```cpp +// mrdocs::for buffer_param-0e buffer_param-0c +``` + +The names are MrDocs anchors, which you can read from the generated reference. +Without this, every symbol sharing the file takes every example in it, and an +overload page shows its siblings' examples. + +## Checks + +- `boost_capy_doc_tests` compiles these files with `-Wall -Wextra -Werror`. +- The docs workflow asserts the number of injected examples, because a MrDocs + without the extension installed ignores the script and renders the reference + with no examples at all while still reporting success. +- Five `@code` blocks remain in headers: MrDocs does not publish those symbols, + so there is nothing to inject them into. + +## Requirements + +Injection needs MrDocs' extension API, which is not in any tagged release -- +corpus transforms arrived in cppalliance/mrdocs#1196 and script-driven +generators in #1218, both after v0.8.0. + +`doc/build_antora.sh` downloads a develop build, copies +`doc/addons/extensions/*.lua` into `/share/mrdocs/addons/extensions/`, +and exports `MRDOCS_ROOT` so the Antora reference extension uses it instead of +downloading its own. Doing it there rather than in CI means every caller gets +it: this repository's docs workflow, the C++ Alliance doc build, and a plain +local run. + +Set `MRDOCS_ROOT` yourself to build against a specific MrDocs; the extension is +copied into whatever install is used. Note that setting a `version` for the +reference extension in `doc/local-playbook.yml` makes it reject a local install +and download its own, which silently produces a reference with no examples. diff --git a/test/doc/reference/ReadStream.concept.cpp b/test/doc/reference/ReadStream.concept.cpp new file mode 100644 index 000000000..141aca66c --- /dev/null +++ b/test/doc/reference/ReadStream.concept.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::ReadStream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/read_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +template< MutableBufferSequence MB > +IoAwaitable auto read_some( MB buffers ); +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +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 ) ); + total += n; + if( ec ) + co_return; + } +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/Stream.concept.cpp b/test/doc/reference/Stream.concept.cpp new file mode 100644 index 000000000..44f2c7704 --- /dev/null +++ b/test/doc/reference/Stream.concept.cpp @@ -0,0 +1,84 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::Stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +template +task<> echo(S& stream) +{ + char buf[1024]; + auto [ec, n] = co_await stream.read_some(make_buffer(buf)); + if(ec) + co_return; + + // write_some may transfer fewer than n bytes (the partial-write + // contract it inherits from WriteStream), so loop until every + // byte read is written, or an error stops the loop early. + std::size_t total = 0; + while(total < n) + { + auto [ec2, n2] = co_await stream.write_some( + const_buffer(buf + total, n - total)); + total += n2; + if(ec2) + co_return; + } +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/WriteStream.concept.cpp b/test/doc/reference/WriteStream.concept.cpp new file mode 100644 index 000000000..ed5def1e0 --- /dev/null +++ b/test/doc/reference/WriteStream.concept.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::WriteStream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/write_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +template< ConstBufferSequence Buffers > +IoAwaitable auto write_some( Buffers buffers ); +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +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 ) ); + total += n; + if( ec ) + co_return; + } +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/any_executor.record.cpp b/test/doc/reference/any_executor.record.cpp new file mode 100644 index 000000000..1a023fdcc --- /dev/null +++ b/test/doc/reference/any_executor.record.cpp @@ -0,0 +1,78 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::any_executor, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/any_executor.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// c must stay at a stable address until the executor dequeues it, so +// the caller owns it -- typically as part of the awaitable or +// operation state that posts it, never as a callee-local temporary. +void dispatch_via_context(thread_pool& ctx, continuation& c) +{ + any_executor exec = ctx.get_executor(); + if(exec) + { + auto& context = exec.context(); + // dispatch() may hand the continuation straight back for + // symmetric transfer instead of enqueuing it, so the returned + // handle must be resumed or the continuation is dropped. + exec.dispatch(c).resume(); + } +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/any_read_stream.record.cpp b/test/doc/reference/any_read_stream.record.cpp new file mode 100644 index 000000000..08969217f --- /dev/null +++ b/test/doc/reference/any_read_stream.record.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::any_read_stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/io/any_read_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// A minimal ReadStream: completes immediately, reporting +// the whole buffer sequence as read. +struct instant_stream +{ + template + auto read_some(MB buffers) + { + return ready(buffer_size(buffers)); + } +}; + +task<> use_any_read_stream() +{ + // Owning - takes ownership of the stream + any_read_stream owning_stream(instant_stream{}); + + // Reference - wraps without ownership + instant_stream instant; + any_read_stream ref_stream(&instant); + + char data[1024]; + mutable_buffer buf(data, sizeof(data)); + auto [ec, n] = co_await owning_stream.read_some(buf); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/any_stream.record.cpp b/test/doc/reference/any_stream.record.cpp new file mode 100644 index 000000000..1845deabf --- /dev/null +++ b/test/doc/reference/any_stream.record.cpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::any_stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/io/any_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// A minimal bidirectional stream: both operations complete +// immediately, reporting the whole buffer sequence transferred. +struct instant_stream +{ + template + auto read_some(MB buffers) + { + return ready(buffer_size(buffers)); + } + + template + auto write_some(CB buffers) + { + return ready(buffer_size(buffers)); + } +}; + +void reader(any_read_stream&) {} +void writer(any_write_stream&) {} + +task<> use_any_stream() +{ + // Owning - takes ownership of the stream + any_stream owning_stream(instant_stream{}); + + // Reference - wraps without ownership + instant_stream instant; + any_stream ref_stream(&instant); + + // Use read_some from the any_read_stream base + char rdata[1024]; + mutable_buffer rbuf(rdata, sizeof(rdata)); + auto [ec1, n1] = co_await owning_stream.read_some(std::span(&rbuf, 1)); + + // Use write_some from the any_write_stream base + char wdata[] = "hello"; + const_buffer wbuf(wdata, sizeof(wdata)); + auto [ec2, n2] = co_await owning_stream.write_some(std::span(&wbuf, 1)); + + // Pass to functions expecting one capability + reader(owning_stream); // Implicit upcast + writer(owning_stream); // Implicit upcast +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/any_write_stream.record.cpp b/test/doc/reference/any_write_stream.record.cpp new file mode 100644 index 000000000..e2c148fa5 --- /dev/null +++ b/test/doc/reference/any_write_stream.record.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::any_write_stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/io/any_write_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// A minimal WriteStream: completes immediately, reporting +// the whole buffer sequence as written. +struct instant_stream +{ + template + auto write_some(CB buffers) + { + return ready(buffer_size(buffers)); + } +}; + +task<> use_any_write_stream() +{ + // Owning - takes ownership of the stream + any_write_stream owning_stream(instant_stream{}); + + // Reference - wraps without ownership + instant_stream instant; + any_write_stream ref_stream(&instant); + + char data[] = "hello"; + const_buffer buf(data, sizeof(data)); + auto [ec, n] = co_await owning_stream.write_some(std::span(&buf, 1)); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/async_event.record.cpp b/test/doc/reference/async_event.record.cpp new file mode 100644 index 000000000..3e18c5e2a --- /dev/null +++ b/test/doc/reference/async_event.record.cpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::async_event, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/async_event.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::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 + co_return; +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/async_mutex.record.cpp b/test/doc/reference/async_mutex.record.cpp new file mode 100644 index 000000000..123a813b3 --- /dev/null +++ b/test/doc/reference/async_mutex.record.cpp @@ -0,0 +1,81 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::async_mutex, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/async_mutex.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::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_raii() { + auto [ec, guard] = co_await cm.scoped_lock(); + if(ec) + co_return; + // ... critical section ... + // unlocks automatically +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/async_waker.record.cpp b/test/doc/reference/async_waker.record.cpp new file mode 100644 index 000000000..c7dec87a7 --- /dev/null +++ b/test/doc/reference/async_waker.record.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::async_waker, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/async_waker.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +void waker_example() +{ + async_waker waker; + + // user-provided timing thread + std::thread th([&waker] { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + waker.wake(); + }); + + auto waiter = [&waker]() -> task<> { + auto [ec] = co_await waker.wait(); + // resumed on the executor after ~100ms + }; + + // ... run waiter() on an executor and let the pool drain + + th.join(); // waker.wake() has run; safe to destroy waker now +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/awaitable_decomposes_to.concept.cpp b/test/doc/reference/awaitable_decomposes_to.concept.cpp new file mode 100644 index 000000000..7c41da108 --- /dev/null +++ b/test/doc/reference/awaitable_decomposes_to.concept.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::awaitable_decomposes_to, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/decomposes_to.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// Constrain a function to accept only awaitables that return +// a decomposable result of (error_code, size_t) +template + requires awaitable_decomposes_to +task process(A&& op) +{ + auto [ec, n] = co_await std::forward(op); + if (ec) + co_return; + // process n bytes... +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/buffer_param.record.cpp b/test/doc/reference/buffer_param.record.cpp new file mode 100644 index 000000000..9e27880f9 --- /dev/null +++ b/test/doc/reference/buffer_param.record.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::buffer_param, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/buffers/buffer_param.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example_1[] +task<> write(ConstBufferSequence auto buffers); // CORRECT +task<> write(ConstBufferSequence auto& buffers); // WRONG - dangling reference +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +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); + } +} +// end::example_2[] +} // namespace ex_2 +namespace ex_3 { +// tag::example_3[] +class base +{ +public: + template + task<> write(BS buffers) + { + const_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 buffers, + std::size_t& bytes_written) = 0; +}; +// end::example_3[] +} // namespace ex_3 + +} // namespace diff --git a/test/doc/reference/buffer_size.function.cpp b/test/doc/reference/buffer_size.function.cpp new file mode 100644 index 000000000..07d02bc6a --- /dev/null +++ b/test/doc/reference/buffer_size.function.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::buffer_size, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/buffers.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +unsigned char header[16]; +unsigned char payload[512]; +std::array bufs = { + mutable_buffer( header, sizeof(header) ), + mutable_buffer( payload, sizeof(payload) ) }; +std::size_t total = buffer_size( bufs ); // 16 + 512 +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/buffer_slice.function.cpp b/test/doc/reference/buffer_slice.function.cpp new file mode 100644 index 000000000..ebe388ae5 --- /dev/null +++ b/test/doc/reference/buffer_slice.function.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::buffer_slice, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/buffers/buffer_slice.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task<> send_in_two_parts( any_write_stream& sock, const_buffer bufs ) +{ + co_await write(sock, buffer_slice(bufs, 0, 16384)); // first 16 KB + auto rest = buffer_slice(bufs, 16384); // drop first 16 KB + co_await write(sock, rest); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/cond.enum.cpp b/test/doc/reference/cond.enum.cpp new file mode 100644 index 000000000..ef70c7cce --- /dev/null +++ b/test/doc/reference/cond.enum.cpp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::cond, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/cond.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task<> classify_read_error( any_read_stream& stream, mutable_buffer bufs ) +{ + 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 + } +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/const_buffer_archetype_.record.cpp b/test/doc/reference/const_buffer_archetype_.record.cpp new file mode 100644 index 000000000..3ea59c485 --- /dev/null +++ b/test/doc/reference/const_buffer_archetype_.record.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::const_buffer_archetype_, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/buffer_archetype.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +template +concept MyWritable = + requires(T& stream, const_buffer_archetype buffers) + { + stream.write(buffers); + }; +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/consuming_buffers.record.cpp b/test/doc/reference/consuming_buffers.record.cpp new file mode 100644 index 000000000..e848313f9 --- /dev/null +++ b/test/doc/reference/consuming_buffers.record.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::consuming_buffers, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/buffers/consuming_buffers.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example[] +template +io_task read_until_full( any_read_stream& stream, Buffers buffers ) +{ + consuming_buffers consuming(buffers); + std::size_t total = 0, want = buffer_size(buffers); + while (total < want) + { + auto [ec, n] = co_await stream.read_some(consuming.data()); + consuming.consume(n); + total += n; + if (ec && total < want) co_return {ec, total}; + } + co_return {std::error_code(), total}; +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/decomposes_to.concept.cpp b/test/doc/reference/decomposes_to.concept.cpp new file mode 100644 index 000000000..43648b2ac --- /dev/null +++ b/test/doc/reference/decomposes_to.concept.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::decomposes_to, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/decomposes_to.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +struct result { int a; double b; }; + +static_assert(decomposes_to); +static_assert(decomposes_to, int, double>); +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/execution_context.record.cpp b/test/doc/reference/execution_context.record.cpp new file mode 100644 index 000000000..4db6f70a5 --- /dev/null +++ b/test/doc/reference/execution_context.record.cpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::execution_context, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/execution_context.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::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(); + } +}; + +void configure_services(io_context& ctx) +{ + ctx.make_service(); + ctx.find_service(); // returns posix_file_service* + ctx.find_service(); // also works +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/execution_context__service.record.cpp b/test/doc/reference/execution_context__service.record.cpp new file mode 100644 index 000000000..132c4d3f8 --- /dev/null +++ b/test/doc/reference/execution_context__service.record.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::execution_context::service, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/execution_context.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +struct my_service : execution_context::service +{ + explicit my_service(execution_context&) {} + +protected: + void shutdown() override + { + // Cancel pending operations, release resources + } +}; +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/executor_ref.record.cpp b/test/doc/reference/executor_ref.record.cpp new file mode 100644 index 000000000..89d413800 --- /dev/null +++ b/test/doc/reference/executor_ref.record.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::executor_ref, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/executor_ref.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// my_continuation must stay at a stable address until the executor +// dequeues it, so it is owned by the caller, not by store_executor(). +void store_executor(executor_ref ex, continuation& my_continuation) +{ + if(ex) + ex.post(my_continuation); +} + +void use_thread_pool(thread_pool& ctx, continuation& my_continuation) +{ + store_executor(ctx.get_executor(), my_continuation); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/frame_alloc_mixin.record.cpp b/test/doc/reference/frame_alloc_mixin.record.cpp new file mode 100644 index 000000000..4a87b7aa0 --- /dev/null +++ b/test/doc/reference/frame_alloc_mixin.record.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::frame_alloc_mixin, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/frame_alloc_mixin.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +struct my_internal_coroutine +{ + struct promise_type : frame_alloc_mixin + { + my_internal_coroutine get_return_object(); + std::suspend_always initial_suspend() noexcept; + std::suspend_always final_suspend() noexcept; + void return_void(); + void unhandled_exception() noexcept; + }; +}; +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/immediate.record.cpp b/test/doc/reference/immediate.record.cpp new file mode 100644 index 000000000..81f2e2c9e --- /dev/null +++ b/test/doc/reference/immediate.record.cpp @@ -0,0 +1,94 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::immediate, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/immediate.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +// Wrap a sync operation as an awaitable +immediate get_value() +{ + return {42}; +} + +task example() +{ + int x = co_await get_value(); // No suspension, returns 42 +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +struct my_sync_sink +{ + template + immediate> + write(CB buffers) + { + auto n = process_sync(buffers); + return {{std::error_code(), n}}; + } + + immediate> + write_eof() + { + return {{}}; + } +}; +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/io_awaitable_promise_base.record.cpp b/test/doc/reference/io_awaitable_promise_base.record.cpp new file mode 100644 index 000000000..ac11803a1 --- /dev/null +++ b/test/doc/reference/io_awaitable_promise_base.record.cpp @@ -0,0 +1,187 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::io_awaitable_promise_base, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/io_awaitable_promise_base.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +// Both examples on this page show the same minimal promise_type +// deliberately: the point here is the mixin's environment access, not +// variations on promise plumbing. +struct my_task +{ + struct promise_type : io_awaitable_promise_base + { + my_task get_return_object() + { + return my_task{std::coroutine_handle::from_promise(*this)}; + } + std::suspend_always initial_suspend() noexcept { return {}; } + + // Resumes the awaiting coroutine by symmetric transfer, as the + // base class requires: the continuation stored by + // set_continuation() must be handed back here, or the awaiting + // coroutine is never resumed. + auto final_suspend() noexcept + { + struct awaiter + { + promise_type* p_; + bool await_ready() const noexcept { return false; } + std::coroutine_handle<> + await_suspend(std::coroutine_handle<>) const noexcept + { + return p_->continuation(); + } + void await_resume() const noexcept {} + }; + return awaiter{this}; + } + void return_void() {} + + // Capture rather than swallow. A real awaitable rethrows + // this from its own await_resume(). + void unhandled_exception() noexcept { ep_ = std::current_exception(); } + + std::exception_ptr ep_; + }; + + std::coroutine_handle h; +}; + +my_task example() +{ + auto env = co_await this_coro::environment; + // Access env->executor, env->stop_token, env->frame_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::frame_allocator; +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +struct promise_type : io_awaitable_promise_base +{ + template + auto transform_awaitable(A&& a) + { + // Your custom transformation logic + return std::forward(a); + } +}; +// end::example_2[] +} // namespace ex_2 + +namespace ex_3 { +// tag::example_3[] +// Same minimal promise_type as the Basic Usage example above -- this +// section's point is the await_suspend overload below, not the promise. +struct my_task +{ + struct promise_type : io_awaitable_promise_base + { + my_task get_return_object() + { + return my_task{std::coroutine_handle::from_promise(*this)}; + } + std::suspend_always initial_suspend() noexcept { return {}; } + + // Resumes the awaiting coroutine by symmetric transfer, as the + // base class requires: the continuation stored by + // set_continuation() must be handed back here, or the awaiting + // coroutine is never resumed. + auto final_suspend() noexcept + { + struct awaiter + { + promise_type* p_; + bool await_ready() const noexcept { return false; } + std::coroutine_handle<> + await_suspend(std::coroutine_handle<>) const noexcept + { + return p_->continuation(); + } + void await_resume() const noexcept {} + }; + return awaiter{this}; + } + void return_void() {} + + // Capture rather than swallow. A real awaitable rethrows + // this from its own await_resume(). + void unhandled_exception() noexcept { ep_ = std::current_exception(); } + + std::exception_ptr ep_; + }; + + std::coroutine_handle h_; + + // IoAwaitable await_suspend receives and stores the environment, + // then resumes into the coroutine body via symmetric transfer + std::coroutine_handle<> await_suspend(std::coroutine_handle<> cont, io_env const* env) + { + h_.promise().set_continuation(cont); + h_.promise().set_environment(env); + return h_; + } +}; +// end::example_3[] +} // namespace ex_3 + +} // namespace diff --git a/test/doc/reference/io_result.typedef.cpp b/test/doc/reference/io_result.typedef.cpp new file mode 100644 index 000000000..e6b2a6cf9 --- /dev/null +++ b/test/doc/reference/io_result.typedef.cpp @@ -0,0 +1,80 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::io_result, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/io_result.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example_1[] +task<> discard_first_chunk( any_read_stream& s, mutable_buffer buf ) +{ + auto [ec, n] = co_await s.read_some(buf); + if (ec) + co_return; // error: n's meaning here is defined by read_some +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +task<> read_into_locals( any_read_stream& s, mutable_buffer buf ) +{ + std::error_code ec; + std::size_t n = 0; + std::tie(ec, n) = co_await s.read_some(buf); +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/io_task.typedef.cpp b/test/doc/reference/io_task.typedef.cpp new file mode 100644 index 000000000..4e5eb3b76 --- /dev/null +++ b/test/doc/reference/io_task.typedef.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::io_task, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/io_task.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +io_task read_one( any_read_stream& s, mutable_buffer buf ) +{ + co_return co_await s.read_some(buf); // returns io_result +} + +io_task<> require_ready(bool ready) +{ + if(!ready) + co_return make_error_code(error::eof); // error_code converts to io_result<> + co_return {}; +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/mutable_buffer_archetype_.record.cpp b/test/doc/reference/mutable_buffer_archetype_.record.cpp new file mode 100644 index 000000000..3272db5a0 --- /dev/null +++ b/test/doc/reference/mutable_buffer_archetype_.record.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::mutable_buffer_archetype_, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/concept/buffer_archetype.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +template +concept MyReadable = + requires(T& stream, mutable_buffer_archetype buffers) + { + stream.read(buffers); + }; +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/operator_.function.cpp b/test/doc/reference/operator_.function.cpp new file mode 100644 index 000000000..06ca6279c --- /dev/null +++ b/test/doc/reference/operator_.function.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for operator(), injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/buffers.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +unsigned char header[16]; +unsigned char payload[512]; +std::array bufs = { + mutable_buffer( header, sizeof(header) ), + mutable_buffer( payload, sizeof(payload) ) }; +std::size_t total = buffer_size( bufs ); // 16 + 512 +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/read.function.cpp b/test/doc/reference/read.function.cpp new file mode 100644 index 000000000..41fe6d79f --- /dev/null +++ b/test/doc/reference/read.function.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::read, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/read.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +capy::task<> process_message(capy::ReadStream auto& stream) +{ + std::vector header(16); // known header size for some protocol + auto [ec, n] = co_await capy::read(stream, capy::make_buffer(header)); + if (ec == capy::cond::eof) + co_return; // Connection closed + if (ec) + throw std::system_error(ec); + + // at this point `header` contains exactly 16 bytes +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/read_at_least.function.cpp b/test/doc/reference/read_at_least.function.cpp new file mode 100644 index 000000000..752bc4742 --- /dev/null +++ b/test/doc/reference/read_at_least.function.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::read_at_least, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/read_at_least.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +capy::task<> fill_buffer(capy::ReadStream auto& stream) +{ + std::vector storage(4096); // generous capacity + // Require 16 header bytes; opportunistically take more. + auto [ec, n] = co_await capy::read_at_least( + stream, capy::make_buffer(storage), 16); + if(ec) + throw std::system_error(ec); + + // at least 16 bytes are available; n may be larger +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/ready.function.cpp b/test/doc/reference/ready.function.cpp new file mode 100644 index 000000000..1823e72f4 --- /dev/null +++ b/test/doc/reference/ready.function.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::ready, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/immediate.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example_1[] +std::size_t write_all_sync(const_buffer buf) +{ + return buffer_size(buf); +} + +std::error_code connect_sync() +{ + return {}; +} + +immediate> +write(const_buffer buf) +{ + auto n = write_all_sync(buf); + return ready(n); // success with n bytes +} + +immediate> +connect() +{ + connect_sync(); + return ready(); // void success +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +std::error_code write_checked_sync(const_buffer buf) +{ + if(buffer_size(buf) == 0) + return std::make_error_code(std::errc::invalid_argument); + return {}; +} + +immediate> +write(const_buffer buf) +{ + auto ec = write_checked_sync(buf); + if(ec) + return ready(ec, std::size_t{0}); + return ready(buffer_size(buf)); +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/recycling_memory_resource.record.cpp b/test/doc/reference/recycling_memory_resource.record.cpp new file mode 100644 index 000000000..91cb70d59 --- /dev/null +++ b/test/doc/reference/recycling_memory_resource.record.cpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::recycling_memory_resource, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/recycling_memory_resource.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task my_task() { co_return; } + +void run_with_recycling( any_executor ex ) +{ + auto* mr = get_recycling_memory_resource(); + run_async(ex, mr)(my_task()); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/run.function.cpp b/test/doc/reference/run.function.cpp new file mode 100644 index 000000000..b94a3963e --- /dev/null +++ b/test/doc/reference/run.function.cpp @@ -0,0 +1,80 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::run, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/run.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example_1[] +task cancellable_task() { co_return; } + +task override_stop_token() +{ + std::stop_source source; + co_await run(source.get_token())(cancellable_task()); +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +task my_task() { co_return; } + +task switch_executor( any_executor other_executor ) +{ + co_await run(other_executor)(my_task()); +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/run_async.function.cpp b/test/doc/reference/run_async.function.cpp new file mode 100644 index 000000000..c615d93e7 --- /dev/null +++ b/test/doc/reference/run_async.function.cpp @@ -0,0 +1,137 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::run_async, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/run_async.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example_1[] +task my_task() { co_return; } + +void start_task( any_executor ex ) +{ + run_async(ex)(my_task()); +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +task compute_value() { co_return 42; } + +template +struct overloaded : Fs... { using Fs::operator()...; }; +template +overloaded(Fs...) -> overloaded; + +// The handlers may run after this function returns, on whichever thread +// the executor schedules them, so the state they write must outlive +// the call. +int last_result = 0; +int last_result2 = 0; +bool last_failed = false; + +void run_with_result_handler_demo( any_executor ex ) +{ + run_async(ex, [](int result) { + last_result = result; // the successful value arrives here + })(compute_value()); + + // Overloaded handler for both result and exception + overloaded handle_result_or_exception{ + [](int result) { last_result2 = result; }, // the successful value arrives here + [](std::exception_ptr) { last_failed = true; } // the failure arrives here + }; + run_async(ex, handle_result_or_exception)(compute_value()); +} +// end::example_2[] +} // namespace ex_2 +namespace ex_3 { +// tag::example_3[] +task compute_value() { co_return 42; } + +// The handlers may run after this function returns, on whichever thread +// the executor schedules them, so the state they write must outlive +// the call. +int separate_handlers_result = 0; +std::string separate_handlers_error; + +void run_with_separate_handlers_demo( any_executor ex ) +{ + run_async(ex, + [](int result) { + separate_handlers_result = result; // the successful value arrives here + }, + [](std::exception_ptr ep) { + try { std::rethrow_exception(ep); } + catch (std::exception const& e) { + separate_handlers_error = e.what(); // copied: the message outlives the exception + } + } + )(compute_value()); +} +// end::example_3[] +} // namespace ex_3 +namespace ex_4 { +// tag::example_4[] +task cancellable_task() { co_return; } + +void run_with_cancellation( any_executor ex ) +{ + std::stop_source source; + run_async(ex, source.get_token())(cancellable_task()); + // Later: source.request_stop(); +} +// end::example_4[] +} // namespace ex_4 + +} // namespace diff --git a/test/doc/reference/run_async_wrapper.record.cpp b/test/doc/reference/run_async_wrapper.record.cpp new file mode 100644 index 000000000..eb19ea45b --- /dev/null +++ b/test/doc/reference/run_async_wrapper.record.cpp @@ -0,0 +1,91 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::run_async_wrapper, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/run_async.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task my_task() { co_return; } + +void correct_usage( any_executor ex ) +{ + // Correct usage - wrapper is temporary, task is the direct argument + run_async(ex)(my_task()); +} + +void rvalue_only_call( any_executor ex ) +{ + // Compiles - copy elision constructs w directly from the prvalue + auto w = run_async(ex); + + // Calling on the rvalue is the supported form; calling through + // the stored lvalue is rejected by the rvalue ref-qualifier. + using wrapper = decltype(w); + static_assert( std::is_invocable_v< wrapper, task > ); + static_assert( ! std::is_invocable_v< wrapper&, task > ); + + std::move(w)(my_task()); // Compiles: w is now an rvalue +} + +void silent_misuse( any_executor ex ) +{ + // Compiles, but WRONG - task frame allocated before run_async runs + auto t = my_task(); + run_async(ex)(std::move(t)); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/strand.record.cpp b/test/doc/reference/strand.record.cpp new file mode 100644 index 000000000..cf90911eb --- /dev/null +++ b/test/doc/reference/strand.record.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::strand, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/strand.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +// Continuations are linked intrusively into the strand's queue, so +// each must outlive its time there. The caller owns c1/c2/c3 -- +// typically as members of the awaitable or operation state that +// posts them, never as locals that go out of scope while enqueued. +void post_three(thread_pool& pool, + continuation& c1, continuation& c2, continuation& c3) +{ + strand sd(pool.get_executor()); // CTAD deduces the executor type + + sd.post(c1); + sd.post(c2); + sd.post(c3); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/task.record.cpp b/test/doc/reference/task.record.cpp new file mode 100644 index 000000000..a843a2fd3 --- /dev/null +++ b/test/doc/reference/task.record.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::task, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/task.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task compute_value( any_read_stream& stream, mutable_buffer buf ) +{ + auto [ec, n] = co_await stream.read_some( buf ); + if( ec ) + co_return 0; + co_return static_cast( n ); +} + +task<> run_session( any_read_stream& stream, mutable_buffer buf ) +{ + int result = co_await compute_value( stream, buf ); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/test__buffer_to_string.function.cpp b/test/doc/reference/test__buffer_to_string.function.cpp new file mode 100644 index 000000000..41e8d14d5 --- /dev/null +++ b/test/doc/reference/test__buffer_to_string.function.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::buffer_to_string, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/buffer_to_string.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example[] +task<> +buffer_to_string_examples() +{ + // Single buffer sequence + const_buffer cb( "hello", 5 ); + BOOST_TEST_EQ( buffer_to_string( cb ), "hello" ); + + // Multiple buffer sequences (concatenation) + const_buffer b1( "hello", 5 ); + const_buffer b2( " world", 6 ); + BOOST_TEST_EQ( buffer_to_string( b1, b2 ), "hello world" ); + + // With bufgrind splits: each half is itself a buffer sequence, + // so pass it directly -- there is no .data() to unwrap. + bufgrind bg( cb ); + while( bg ) { + auto [h1, h2] = co_await bg.next(); + BOOST_TEST_EQ( buffer_to_string( h1, h2 ), "hello" ); + } +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/test__bufgrind.record.cpp b/test/doc/reference/test__bufgrind.record.cpp new file mode 100644 index 000000000..993abe173 --- /dev/null +++ b/test/doc/reference/test__bufgrind.record.cpp @@ -0,0 +1,123 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::bufgrind, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/bufgrind.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example_1[] +void +bufgrind_walk_splits_demo() +{ + // Test all split points of a buffer + std::string data = "hello world"; + auto cb = make_buffer( data ); + + fuse f; + auto r = f.inert( [&]( fuse& ) -> task<> { + bufgrind bg( cb ); + while( bg ) { + auto [b1, b2] = co_await bg.next(); + // b1 contains first N bytes (as a buffer sequence) + // b2 contains remaining bytes (as a buffer sequence) + // concatenating b1 + b2 equals original + BOOST_TEST( buffer_to_string( b1, b2 ) == data ); + } + } ); +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +// Mutable buffers preserve mutability +char data[100]; +mutable_buffer buf( data, sizeof( data ) ); + +task<> +bufgrind_walk_mutable() +{ + bufgrind bg( buf ); + while( bg ) { + auto [b1, b2] = co_await bg.next(); + // b1, b2 yield mutable_buffer when iterated + static_assert( MutableBufferSequence ); + static_assert( MutableBufferSequence ); + } +} +// end::example_2[] +} // namespace ex_2 + +namespace ex_3 { +// tag::example_3[] +// Skip by 10 bytes for faster iteration +const_buffer bufgrind_step_data( "0123456789ABCDE", 15 ); + +task<> +bufgrind_walk_by_step() +{ + bufgrind bg( bufgrind_step_data, 10 ); + while( bg ) { + auto [b1, b2] = co_await bg.next(); + // Visits positions 0, 10, 20, ..., and always size + } +} +// end::example_3[] +} // namespace ex_3 + +} // namespace diff --git a/test/doc/reference/test__fuse.record.cpp b/test/doc/reference/test__fuse.record.cpp new file mode 100644 index 000000000..ab4f3463b --- /dev/null +++ b/test/doc/reference/test__fuse.record.cpp @@ -0,0 +1,210 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example_1[] +void basic_inline_usage() +{ + fuse()([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + + ec = f.maybe_fail(); + if(ec) + return; + }); +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +void named_fuse_with_armed() +{ + struct MyObject + { + fuse& f; + explicit MyObject(fuse& f) : f(f) {} + + void do_something() + { + auto ec = f.maybe_fail(); + if(ec) + return; + } + }; + + fuse f; + MyObject obj(f); + auto r = f.armed([&](fuse&) { + obj.do_something(); + }); +} +// end::example_2[] +} // namespace ex_2 + +namespace ex_3 { +// tag::example_3[] +void inert_single_run_test(bool some_condition) +{ + fuse f; + auto r = f.inert([&](fuse& f) { + auto ec = f.maybe_fail(); // Always succeeds + if(some_condition) + f.fail(); // Only way to signal failure + }); +} +// end::example_3[] +} // namespace ex_3 + +namespace ex_4 { +// tag::example_4[] +void dependency_injection_standalone_usage() +{ + class MyService + { + fuse& f_; + public: + explicit MyService(fuse& f) : f_(f) {} + + std::error_code do_work() + { + auto ec = f_.maybe_fail(); // No-op outside armed/inert + if(ec) + return ec; + // ... actual work ... + return {}; + } + }; + + // Production usage - fuse is no-op + fuse f; + MyService svc(f); + svc.do_work(); // maybe_fail() returns {} always + + // Test usage - failures are injected + auto r = f.armed([&](fuse&) { + svc.do_work(); // maybe_fail() triggers failures + }); +} +// end::example_4[] +} // namespace ex_4 + +namespace ex_5 { +// tag::example_5[] +auto custom_ec = make_error_code( + std::errc::operation_canceled); +fuse f(custom_ec); +auto r = f.armed([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; +}); +// end::example_5[] +} // namespace ex_5 + +namespace ex_6 { +// tag::example_6[] +void checking_the_result() +{ + fuse f; + auto r = f([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + }); + + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_6[] +} // namespace ex_6 + +namespace ex_7 { +// tag::example_7[] +void test_framework_integration() +{ + fuse f; + auto r = f([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + }); + + // BOOST_TEST is capy's own Boost.Test-style assertion macro, + // declared in extra/test_suite/test_suite.hpp and included as + // "test_suite.hpp". A Catch2 suite would spell the same check + // REQUIRE(r.success). + BOOST_TEST(r.success); + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_7[] +} // namespace ex_7 + +} // namespace diff --git a/test/doc/reference/test__fuse__armed.function.cpp b/test/doc/reference/test__fuse__armed.function.cpp new file mode 100644 index 000000000..c8f52b62f --- /dev/null +++ b/test/doc/reference/test__fuse__armed.function.cpp @@ -0,0 +1,144 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::armed, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { +namespace ex_1 { +// tag::example_1[] +// This runner drives each iteration on a background thread via +// thread_pool, rather than run_blocking's single-threaded event +// loop -- demonstrating that armed() only needs a way to run the +// task to completion and report any exception, not any +// particular kind of executor. join() blocks until the posted +// task and its handlers have finished, so ep is safe to read +// once it returns. +std::exception_ptr run_one_iteration(task<> t) +{ + thread_pool pool(1); + std::exception_ptr ep; + run_async(pool.get_executor(), + [](auto&&...) {}, + [&](std::exception_ptr e) { ep = e; } + )(std::move(t)); + pool.join(); + return ep; +} + +void armed_with_custom_runner() +{ + fuse f; + auto r = f.armed(run_one_iteration, + [](fuse& f) -> task<> + { + auto ec = f.maybe_fail(); + if(ec) + co_return; + }); +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +void armed_basic_two_points() +{ + fuse f; + auto r = f.armed([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + + ec = f.maybe_fail(); + if(ec) + return; + }); + + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_2[] +} // namespace ex_2 + +namespace ex_3 { +// tag::example_3[] +void armed_coroutine_two_points() +{ + fuse f; + auto r = f.armed([&](fuse&) -> task { + auto ec = f.maybe_fail(); + if(ec) + co_return; + + ec = f.maybe_fail(); + if(ec) + co_return; + }); + + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_3[] +} // namespace ex_3 + +} // namespace diff --git a/test/doc/reference/test__fuse__fail.function.cpp b/test/doc/reference/test__fuse__fail.function.cpp new file mode 100644 index 000000000..fc62b383d --- /dev/null +++ b/test/doc/reference/test__fuse__fail.function.cpp @@ -0,0 +1,121 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::fail, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { +namespace ex_1 { +// tag::example_1[] +void fail_on_unmet_condition(int some_value, int expected) +{ + fuse f; + auto r = f([&](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + + // Explicit failure when a condition is not met + if(some_value != expected) + { + f.fail(); + return; + } + }); + + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +void fail_captures_exception(void (*do_something)()) +{ + fuse f; + auto r = f([&](fuse& f) { + try + { + do_something(); + } + catch(...) + { + f.fail(std::current_exception()); + return; + } + }); + + if(!r) + { + std::string message; + try + { + if(r.ep) + std::rethrow_exception(r.ep); + } + catch(std::exception const& e) + { + message = e.what(); // copied: outlives the exception + } + } +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/test__fuse__fuse.function.cpp b/test/doc/reference/test__fuse__fuse.function.cpp new file mode 100644 index 000000000..5b77be0bd --- /dev/null +++ b/test/doc/reference/test__fuse__fuse.function.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::fuse, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { +namespace ex_1 { +// tag::example_1[] +void custom_error_code() +{ + auto custom_ec = make_error_code( + std::errc::operation_canceled); + fuse f(custom_ec); + + std::error_code captured_ec; + auto r = f([&](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + { + captured_ec = ec; + return; + } + }); + + // The fuse delivers the error code it was constructed with, + // not error::test_failure. + BOOST_TEST( captured_ec == custom_ec ); +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +void default_error_code() +{ + fuse f; + std::error_code captured_ec; + + auto r = f([&](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + { + captured_ec = ec; + return; + } + }); + + // A default-constructed fuse delivers error::test_failure. + BOOST_TEST( captured_ec == error::test_failure ); +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/test__fuse__inert.function.cpp b/test/doc/reference/test__fuse__inert.function.cpp new file mode 100644 index 000000000..379aa53e3 --- /dev/null +++ b/test/doc/reference/test__fuse__inert.function.cpp @@ -0,0 +1,114 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::inert, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { +namespace ex_1 { +// tag::example_1[] +void inert_run_once(bool some_condition) +{ + fuse f; + auto r = f.inert([&](fuse& f) { + auto ec = f.maybe_fail(); // Always succeeds + + assert(!ec); // inert() never injects + + // Only way to signal failure: + if(some_condition) + { + f.fail(); + return; + } + }); + + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +void inert_coroutine_run_once(bool some_condition) +{ + fuse f; + auto r = f.inert([&](fuse& f) -> task { + auto ec = f.maybe_fail(); // Always succeeds + + assert(!ec); // inert() never injects + + // Only way to signal failure: + if(some_condition) + { + f.fail(); + co_return; + } + }); + + if(!r) + { + std::cerr << "Failed at " << r.loc.file_name() + << ":" << r.loc.line() << "\n"; + } +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/test__fuse__maybe_fail.function.cpp b/test/doc/reference/test__fuse__maybe_fail.function.cpp new file mode 100644 index 000000000..41235ec95 --- /dev/null +++ b/test/doc/reference/test__fuse__maybe_fail.function.cpp @@ -0,0 +1,86 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::maybe_fail, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example_1[] +fuse f; +auto r = f([](fuse& f) { + // Error code mode: returns the error + auto ec = f.maybe_fail(); + if(ec) + return; + + // Exception mode: throws system_error + ec = f.maybe_fail(); + if(ec) + return; +}); +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +fuse f; +auto ec = f.maybe_fail(); // Always returns {} (no-op) +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/test__fuse__operator_.function.cpp b/test/doc/reference/test__fuse__operator_.function.cpp new file mode 100644 index 000000000..0fdf1df96 --- /dev/null +++ b/test/doc/reference/test__fuse__operator_.function.cpp @@ -0,0 +1,89 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::operator(), injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example[] +void call_operator_is_armed_alias() +{ + // These are equivalent: + fuse f; + auto r1 = f.armed([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + }); + auto r2 = f([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + }); + + // Inline usage: + auto r3 = fuse()([](fuse& f) { + auto ec = f.maybe_fail(); + if(ec) + return; + }); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/test__fuse__result.record.cpp b/test/doc/reference/test__fuse__result.record.cpp new file mode 100644 index 000000000..375a437ab --- /dev/null +++ b/test/doc/reference/test__fuse__result.record.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::fuse::result, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/fuse.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example[] +void inspecting_the_captured_exception() +{ + fuse f; + auto r = f([](fuse& f) { + try + { + throw std::exception(); + } + catch(...) + { + f.fail(std::current_exception()); + } + }); + + // result::ep holds the exception passed to fail(), if any. + if(!r && r.ep) + { + std::string message; + try + { + std::rethrow_exception(r.ep); + } + catch(std::exception const& e) + { + message = e.what(); // copied: outlives the exception + } + } +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/test__read_stream.record.cpp b/test/doc/reference/test__read_stream.record.cpp new file mode 100644 index 000000000..6b68a93a5 --- /dev/null +++ b/test/doc/reference/test__read_stream.record.cpp @@ -0,0 +1,89 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::read_stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/read_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example[] +void +read_stream_armed_demo() +{ + fuse f; + + auto r = f.armed( [&]( fuse& ) -> task { + // Constructed inside the lambda: armed() re-invokes this + // function once per injected failure point, and a + // read_stream constructed outside would carry a stale + // read position across those rounds. + read_stream rs( f ); + rs.provide( "Hello, " ); + rs.provide( "World!" ); + + char buf[32]; + auto [ec, n] = co_await rs.read_some( + mutable_buffer( buf, sizeof( buf ) ) ); + if( ec ) + co_return; + // buf contains "Hello, World!" + } ); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/test__run_blocking.function.cpp b/test/doc/reference/test__run_blocking.function.cpp new file mode 100644 index 000000000..873822b83 --- /dev/null +++ b/test/doc/reference/test__run_blocking.function.cpp @@ -0,0 +1,116 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::run_blocking, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/run_blocking.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { +namespace ex_1 { +// tag::example_1[] +task +compute_example_2() +{ + co_return 7; +} + +void +run_blocking_two_handler_demo() +{ + int result = 0; + run_blocking( + [&](int v) { result = v; }, + [](std::exception_ptr ep) { std::rethrow_exception( ep ); } + )( compute_example_2() ); +} +// end::example_1[] +} // namespace ex_1 + +namespace ex_2 { +// tag::example_2[] +task<> +run_blocking_void_example() +{ + co_return; +} + +void +run_blocking_no_handler_demo() +{ + run_blocking()( run_blocking_void_example() ); +} +// end::example_2[] +} // namespace ex_2 + +namespace ex_3 { +// tag::example_3[] +task +compute_example() +{ + co_return 42; +} + +void +run_blocking_h1_demo() +{ + int result = 0; + run_blocking( [&](int v) { result = v; } )( + compute_example() ); + BOOST_TEST_EQ( result, 42 ); +} +// end::example_3[] +} // namespace ex_3 + +} // namespace diff --git a/test/doc/reference/test__stream.record.cpp b/test/doc/reference/test__stream.record.cpp new file mode 100644 index 000000000..e1045c3e4 --- /dev/null +++ b/test/doc/reference/test__stream.record.cpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example[] +void +stream_pair_armed_demo() +{ + fuse f; + + auto r = f.armed( [&]( fuse& ) -> task<> { + // Constructed inside the lambda: armed() re-invokes this + // function once per injected failure point, and a stream + // pair constructed outside would carry buffered state + // across those rounds. + auto [a, b] = make_stream_pair( f ); + + auto [ec, n] = co_await a.write_some( + const_buffer( "hello", 5 ) ); + if( ec ) + co_return; + + char buf[32]; + auto [ec2, n2] = co_await b.read_some( + mutable_buffer( buf, sizeof( buf ) ) ); + if( ec2 ) + co_return; + // buf contains "hello" + } ); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/test__write_stream.record.cpp b/test/doc/reference/test__write_stream.record.cpp new file mode 100644 index 000000000..98108af5a --- /dev/null +++ b/test/doc/reference/test__write_stream.record.cpp @@ -0,0 +1,86 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::test::write_stream, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/test/write_stream.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include +#include + +#include "test_suite.hpp" + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; +using namespace boost::capy::test; + +namespace { + +namespace ex_1 { +// tag::example[] +void +write_stream_armed_demo() +{ + fuse f; + + auto r = f.armed( [&]( fuse& ) -> task { + // Constructed inside the lambda: armed() re-invokes this + // function once per injected failure point, and a + // write_stream constructed outside would carry + // accumulated data across those rounds. + write_stream ws( f ); + + auto [ec, n] = co_await ws.write_some( + const_buffer( "Hello", 5 ) ); + if( ec ) + co_return; + // ws.data() returns "Hello" + } ); +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/this_coro.namespace.cpp b/test/doc/reference/this_coro.namespace.cpp new file mode 100644 index 000000000..f71593733 --- /dev/null +++ b/test/doc/reference/this_coro.namespace.cpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::this_coro, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/this_coro.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task example() +{ + auto* 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::frame_allocator; +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/this_coro__environment.variable.cpp b/test/doc/reference/this_coro__environment.variable.cpp new file mode 100644 index 000000000..075d937b0 --- /dev/null +++ b/test/doc/reference/this_coro__environment.variable.cpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::this_coro::environment, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/this_coro.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task example() +{ + auto* env = co_await this_coro::environment; + // env->executor - the executor this coroutine is bound to + // env->stop_token - the stop token for cancellation + // env->frame_allocator - the frame allocator +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/this_coro__executor.variable.cpp b/test/doc/reference/this_coro__executor.variable.cpp new file mode 100644 index 000000000..9cce48fdc --- /dev/null +++ b/test/doc/reference/this_coro__executor.variable.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::this_coro::executor, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/this_coro.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task example() +{ + executor_ref ex = co_await this_coro::executor; +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/this_coro__frame_allocator.variable.cpp b/test/doc/reference/this_coro__frame_allocator.variable.cpp new file mode 100644 index 000000000..f0127327e --- /dev/null +++ b/test/doc/reference/this_coro__frame_allocator.variable.cpp @@ -0,0 +1,68 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::this_coro::frame_allocator, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/this_coro.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task example() +{ + auto* alloc = co_await this_coro::frame_allocator; + // alloc is nullptr when using the default allocator +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/this_coro__stop_token.variable.cpp b/test/doc/reference/this_coro__stop_token.variable.cpp new file mode 100644 index 000000000..9accc5976 --- /dev/null +++ b/test/doc/reference/this_coro__stop_token.variable.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::this_coro::stop_token, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/this_coro.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task cancellable_work() +{ + auto token = co_await this_coro::stop_token; + if (token.stop_requested()) + co_return; +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/thread_pool.record.cpp b/test/doc/reference/thread_pool.record.cpp new file mode 100644 index 000000000..8093cb51f --- /dev/null +++ b/test/doc/reference/thread_pool.record.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::thread_pool, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/ex/thread_pool.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +task some_task() { co_return; } + +void run_on_pool() +{ + thread_pool pool(4); // 4 worker threads + auto ex = pool.get_executor(); + run_async(ex)(some_task()); // start work; tracked so join() waits for it + pool.join(); // wait for outstanding work to complete + // pool destructor stops the pool, discarding any pending work +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/when_all.function.cpp b/test/doc/reference/when_all.function.cpp new file mode 100644 index 000000000..f5ef38be3 --- /dev/null +++ b/test/doc/reference/when_all.function.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::when_all, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/when_all.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example_1[] +io_task read_one( any_read_stream& stream, mutable_buffer buf ) +{ + co_return co_await stream.read_some(buf); +} + +task read_all_connections( + std::vector& streams, std::vector& buffers ) +{ + // One awaitable per stream: each stream is touched by exactly one + // child, so running them concurrently is safe. + std::vector> reads; + for (std::size_t i = 0; i < streams.size(); ++i) + reads.push_back(read_one(streams[i], buffers[i])); + + auto [ec, counts] = co_await when_all(std::move(reads)); + if (ec) + { + // handle error + } +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +template< class MakeJob > +task run_n_jobs( MakeJob make_job, int n ) +{ + std::vector> jobs; + for (int i = 0; i < n; ++i) + jobs.push_back(make_job(i)); // io_task<> per index + + auto [ec] = co_await when_all(std::move(jobs)); +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/when_any.function.cpp b/test/doc/reference/when_any.function.cpp new file mode 100644 index 000000000..78b8379e3 --- /dev/null +++ b/test/doc/reference/when_any.function.cpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::when_any, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/when_any.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { +namespace ex_1 { +// tag::example_1[] +io_task read_from( any_read_stream& stream, mutable_buffer buf ) +{ + co_return co_await stream.read_some(buf); +} + +task read_first_ready( + std::vector& streams, std::vector& buffers ) +{ + // One awaitable per stream: each stream is touched by exactly one + // child, so racing them concurrently is safe. + std::vector> reads; + for (std::size_t i = 0; i < streams.size(); ++i) + reads.push_back(read_from(streams[i], buffers[i])); + + auto result = co_await when_any(std::move(reads)); + if (result.index() == 1) + { + auto [idx, n] = std::get<1>(result); // winning stream's slot and byte count + } +} +// end::example_1[] +} // namespace ex_1 +namespace ex_2 { +// tag::example_2[] +io_task<> background_work_a() +{ + co_return {}; +} + +io_task<> background_work_b() +{ + co_return {}; +} + +task example() +{ + std::vector> jobs; + jobs.push_back(background_work_a()); + jobs.push_back(background_work_b()); + + auto result = co_await when_any(std::move(jobs)); + if (result.index() == 1) + { + auto winner = std::get<1>(result); // index of the job that succeeded first + } +} +// end::example_2[] +} // namespace ex_2 + +} // namespace diff --git a/test/doc/reference/work_guard.record.cpp b/test/doc/reference/work_guard.record.cpp new file mode 100644 index 000000000..381c0444f --- /dev/null +++ b/test/doc/reference/work_guard.record.cpp @@ -0,0 +1,55 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples injected into include/boost/capy/ex/work_guard.hpp's +// documentation by doc/addons/extensions/reference-snippets.lua. The tagged +// region is what the reference renders; scaffolding stays outside the tags. + +// Examples deliberately leave results unused; the reference explains the +// values in prose instead. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4505) // unreferenced local function removed +#endif + +#include +#include + +namespace capy = boost::capy; + +namespace { + +using namespace boost::capy; + +// tag::work_guard[] +void keep_alive_while_setting_up() +{ + thread_pool pool(1); + + // Keep the pool from completing while we set things up. Note + // make_work_guard() takes the Executor from get_executor(), not + // the thread_pool context itself. + auto guard = make_work_guard(pool.get_executor()); + + // ... post work to pool ... + + // Allow the pool to complete when work is done + guard.reset(); + + pool.join(); +} +// end::work_guard[] + +} // namespace diff --git a/test/doc/reference/write.function.cpp b/test/doc/reference/write.function.cpp new file mode 100644 index 000000000..816d906d1 --- /dev/null +++ b/test/doc/reference/write.function.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::write, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/write.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +capy::task<> send_response(capy::WriteStream auto& stream, std::string_view body) +{ + auto [ec, n] = co_await capy::write(stream, capy::make_buffer(body)); + if (ec) + throw std::system_error(ec); + + // All bytes written successfully +} +// end::example[] +} // namespace ex_1 + +} // namespace diff --git a/test/doc/reference/write_at_least.function.cpp b/test/doc/reference/write_at_least.function.cpp new file mode 100644 index 000000000..076e5590c --- /dev/null +++ b/test/doc/reference/write_at_least.function.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2026 Michael Vandeberg +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/capy +// + +// Reference examples for boost::capy::write_at_least, injected into its documentation by +// doc/addons/extensions/reference-snippets.lua. Declared in: +// include/boost/capy/write_at_least.hpp +// +// The tagged regions are what the reference renders; the includes, +// suppressions and namespaces around them are scaffolding. Each region gets +// its own namespace so that examples which reuse a name still compile. + +// Examples leave results unused; the reference explains them in prose. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wunused-function" +// gcc 15 with sanitizers misattributes coroutine frame delete paths +#pragma GCC diagnostic ignored "-Wmismatched-new-delete" +#endif +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#if defined(_MSC_VER) +#pragma warning(disable: 4834) // discarding [[nodiscard]] return value +#pragma warning(disable: 4189) // local variable initialized but not referenced +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4101) // unreferenced local variable +#pragma warning(disable: 4456) // declaration hides previous local declaration +#pragma warning(disable: 4457) // declaration hides function parameter +#pragma warning(disable: 4458) // declaration hides class member +#pragma warning(disable: 4459) // declaration hides global declaration +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace capy = boost::capy; +using namespace boost::capy; + +namespace { + +namespace ex_1 { +// tag::example[] +capy::task<> flush_at_least(capy::WriteStream auto& stream, std::string_view data) +{ + auto [ec, n] = co_await capy::write_at_least( + stream, capy::make_buffer(data), 8); + if(ec) + throw std::system_error(ec); + + // at least 8 bytes written; n may be larger +} +// end::example[] +} // namespace ex_1 + +} // namespace