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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions doc/STYLE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ The Antora pipeline provides two mechanisms; use them instead of hand-authoring:
maintainer ruled that B4 binds them anyway: describing what a class *is* is not a licensed
house style, it is the defect B4 exists to catch. Treat both audits' B4 dispositions on class
briefs as superseded; this is what authorizes re-opening that finding set.)*
- **B5. Doc code uses the namespace alias, never a using-directive.** Every file under
`test/doc/`, and every code block authored inline in a `.adoc` page, spells library names
against `namespace capy = boost::capy;` — `capy::task`, `capy::test::fuse`,
`capy::this_coro::executor` — even on a page that never declares the alias itself. A reader
should be able to tell which names in an example come from Capy without knowing the library.
The exception: a block that verbatim-quotes library-internal source keeps that source's own
unqualified spelling. `using namespace boost::capy;` is not used in doc code. Warning
suppressions live in `test/doc/doc_warnings.hpp`, included once per file outside every tag; a
warning that fires in one fragment stays in that fragment with a comment saying why. B5 is
enforced by review only — no script checks it.

## Part C — Wording (pragmatic Simplified Technical English)

Expand Down Expand Up @@ -228,7 +238,7 @@ Not every rule is machine-checkable. Each rule sits in one of three tiers:
|---|---|
| **Gate** | A1, A6, A7, B2, B3, C2, C4, C9, C10, D2 |
| **Warning** | A2, B1, C1, C3, C5, C6, D4, D5, E1 |
| **Review** | A3, A4, A5, B4, C7, C8, C11, D1, D3, E2, E3, E4 |
| **Review** | A3, A4, A5, B4, B5, C7, C8, C11, D1, D3, E2, E3, E4 |

The accuracy gates (B2, B3, D2 correctness) are enforced by the snippet-compile job, not by
Vale — that job is what makes examples unable to drift.
Expand Down Expand Up @@ -294,7 +304,8 @@ max: 25
- **F2.** The snippet-compile job is the accuracy gate; keep every example sourced from a
compiled file (Part B2).
- **F3.** Doc PR checklist: mode declared (A1)? no hand-typed signatures (B1)? example
compiled (B2)? terminology clean (`vale`)? rationale present (D3)?
compiled (B2)? namespace alias, not a using-directive (B5)? terminology clean (`vale`)?
rationale present (D3)?

### F4 — A check is not adopted until a planted violation has failed it

Expand Down
2 changes: 1 addition & 1 deletion doc/modules/ROOT/pages/4.coroutines/4b.launching.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ rvalue-qualified:
.Does not compile
[source,cpp,role=pseudocode]
----
auto wrapper = run_async(pool.get_executor()); // Don't do this
auto wrapper = capy::run_async(pool.get_executor()); // Don't do this
wrapper(compute()); // Error: operator() requires an rvalue
----

Expand Down
2 changes: 1 addition & 1 deletion doc/modules/ROOT/pages/5.buffers/5a.buffers.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ Conversion always happens on the stack; the implementation never allocates. A fi
.Pseudocode - internal implementation
[source,cpp,role=pseudocode]
----
template<ConstBufferSequence Buffers>
template<capy::ConstBufferSequence Buffers>
auto platform_write(Buffers const& buffers)
{
iovec iovecs[16]; // fixed on-frame window, never heap-allocated
Expand Down
8 changes: 4 additions & 4 deletions doc/modules/ROOT/pages/7.testing/7a.drivers.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -213,18 +213,18 @@ task on a context it owns. `run_one` returns any exception the task raised as a
.Excerpt - not compiled here
[source,cpp,role=pseudocode]
----
fuse f;
auto io_runner = [](task<void> t) -> std::exception_ptr {
capy::test::fuse f;
auto io_runner = [](capy::task<void> t) -> std::exception_ptr {
corosio::io_context ioc;
std::exception_ptr ep;
run_async(ioc.get_executor(),
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,
[&](fuse&) -> task<void> {
[&](capy::test::fuse&) -> capy::task<void> {
co_await corosio::timeout(some_op(), 5s);
});
BOOST_TEST(r.success);
Expand Down
3 changes: 2 additions & 1 deletion test/doc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# Copyright (c) 2026 Steve Gerbino
# 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)
Expand Down Expand Up @@ -76,7 +77,7 @@ else()
"[reference-examples] not compiled: they are never executed, and under "
"coverage they only add never-entered template instantiations")
endif()
set(PFILES ${SNIPPETS} ${REFERENCE_SNIPPETS} CMakeLists.txt Jamfile)
set(PFILES ${SNIPPETS} ${REFERENCE_SNIPPETS} doc_warnings.hpp CMakeLists.txt Jamfile)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "" FILES ${PFILES})

add_executable(boost_capy_doc_tests ${PFILES})
Expand Down
57 changes: 57 additions & 0 deletions test/doc/doc_warnings.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// 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
//

#ifndef BOOST_CAPY_TEST_DOC_WARNINGS_HPP
#define BOOST_CAPY_TEST_DOC_WARNINGS_HPP

/* Warning suppressions shared by every compiled documentation fragment.

Fragments and reference examples deliberately leave results and bindings
unused. The pages and the reference explain those values in prose instead,
and adding a use would put code on the page that teaches nothing. test/doc
builds with -Wall -Wextra -Werror (test/doc/CMakeLists.txt and
test/doc/Jamfile), so an unused result would otherwise fail the build.

Include this first in a fragment, and always outside every tag:: region --
the site renders those regions, and scaffolding must not appear on a page.

The pragmas have no push/pop, so they apply to the rest of the translation
unit. That is the intent: a fragment is scaffolding plus tagged regions, and
both need them.

Keep this list minimal. A warning that fires in one fragment belongs in that
fragment, under a comment saying why, not here.
*/

#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

#endif
9 changes: 5 additions & 4 deletions test/doc/programs/4b_launching_run_async.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2026 Steve Gerbino
// 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)
Expand All @@ -11,17 +12,17 @@

// tag::full[]
#include <boost/capy.hpp>
using namespace boost::capy;
namespace capy = boost::capy;

task<int> compute()
capy::task<int> compute()
{
co_return 42;
}

int main()
{
thread_pool pool;
run_async(pool.get_executor())(compute());
capy::thread_pool pool;
capy::run_async(pool.get_executor())(compute());
// Task is now running on the thread pool

pool.join(); // wait for outstanding work to complete
Expand Down
21 changes: 11 additions & 10 deletions test/doc/programs/4c_executors_executor_ref.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2026 Steve Gerbino
// 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)
Expand All @@ -19,11 +20,11 @@
#include <coroutine>
#include <semaphore>

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

namespace {

continuation parked;
capy::continuation parked;
std::binary_semaphore parked_ready{0};

// Suspends its coroutine and publishes the continuation so another
Expand All @@ -33,7 +34,7 @@ struct park
bool await_ready() const noexcept { return false; }

std::coroutine_handle<> await_suspend(
std::coroutine_handle<> h, io_env const*)
std::coroutine_handle<> h, capy::io_env const*)
{
parked.h = h;
parked_ready.release();
Expand All @@ -43,35 +44,35 @@ struct park
void await_resume() {}
};

task<void> parked_task()
capy::task<void> parked_task()
{
co_await park{};
}

// Launch a coroutine on the pool and block until it has parked,
// leaving its continuation ready to be scheduled.
continuation& make_suspended_work(thread_pool& pool)
capy::continuation& make_suspended_work(capy::thread_pool& pool)
{
run_async(pool.get_executor())(parked_task());
capy::run_async(pool.get_executor())(parked_task());
parked_ready.acquire();
return parked;
}

} // namespace

// tag::full[]
void schedule_work(executor_ref ex, continuation& c)
void schedule_work(capy::executor_ref ex, capy::continuation& c)
{
ex.post(c); // Works with any executor
}

int main()
{
thread_pool pool;
capy::thread_pool pool;
auto pool_ex = pool.get_executor();
executor_ref ex = pool_ex; // Type erasure; pool_ex must outlive ex
capy::executor_ref ex = pool_ex; // Type erasure; pool_ex must outlive ex

continuation& c = make_suspended_work(pool); // a coroutine parked on the pool
capy::continuation& c = make_suspended_work(pool); // a coroutine parked on the pool
schedule_work(ex, c);
pool.join();
}
Expand Down
9 changes: 5 additions & 4 deletions test/doc/programs/4c_executors_thread_pool.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2026 Steve Gerbino
// 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)
Expand All @@ -16,9 +17,9 @@
#include <boost/capy/ex/run_async.hpp>
#include <boost/capy/task.hpp>

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

task<void> my_task()
capy::task<void> my_task()
{
co_return;
}
Expand All @@ -27,13 +28,13 @@ task<void> my_task()
int main()
{
// Create pool with 4 threads
thread_pool pool(4);
capy::thread_pool pool(4);

// Get an executor for this pool
auto ex = pool.get_executor();

// Start work on the pool
run_async(ex)(my_task());
capy::run_async(ex)(my_task());

pool.join(); // wait for outstanding work to complete
}
Expand Down
11 changes: 6 additions & 5 deletions test/doc/programs/index_page_echo.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2026 Steve Gerbino
// 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)
Expand All @@ -12,16 +13,16 @@
// tag::full[]
#include <boost/capy.hpp>

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

task<> echo(any_stream& stream)
capy::task<> echo(capy::any_stream& stream)
{
char buf[1024];
for(;;)
{
auto [ec, n] = co_await stream.read_some(make_buffer(buf));
auto [ec, n] = co_await stream.read_some(capy::make_buffer(buf));

auto [wec, wn] = co_await write(stream, const_buffer(buf, n));
auto [wec, wn] = co_await capy::write(stream, capy::const_buffer(buf, n));

if(ec)
co_return;
Expand All @@ -38,7 +39,7 @@ int main()
//
// corosio::io_context ioc;
// corosio::tcp_socket stream = /* from an acceptor or connect */;
// run_async(ioc.get_executor())(echo(stream));
// capy::run_async(ioc.get_executor())(echo(stream));
// ioc.run();
}
// end::full[]
39 changes: 7 additions & 32 deletions test/doc/reference/ExecutionContext.concept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,7 @@
// 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 "../doc_warnings.hpp"

#include <boost/capy.hpp>

Expand All @@ -51,30 +27,29 @@
#include <vector>

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

namespace {

namespace ex_1 {
// tag::example_1[]
class X : public execution_context
class X : public capy::execution_context
{
public:
using executor_type = executor_ref; // any type satisfying Executor
using executor_type = capy::executor_ref; // any type satisfying Executor
executor_type get_executor() noexcept;
};

static_assert( ExecutionContext<X> );
static_assert( capy::ExecutionContext<X> );
// end::example_1[]
} // namespace ex_1

namespace ex_2 {
// tag::example_2[]
template<ExecutionContext Ctx>
void spawn_work( Ctx& ctx, task<> work )
template<capy::ExecutionContext Ctx>
void spawn_work( Ctx& ctx, capy::task<> work )
{
auto ex = ctx.get_executor();
run_async(ex)(std::move(work)); // schedules work; runs on ctx
capy::run_async(ex)(std::move(work)); // schedules work; runs on ctx
}
// end::example_2[]
} // namespace ex_2
Expand Down
Loading
Loading