Skip to content

Comments

this and that#178

Merged
vinniefalco merged 2 commits intocppalliance:developfrom
vinniefalco:develop
Feb 21, 2026
Merged

this and that#178
vinniefalco merged 2 commits intocppalliance:developfrom
vinniefalco:develop

Conversation

@vinniefalco
Copy link
Member

@vinniefalco vinniefalco commented Feb 21, 2026

Summary by CodeRabbit

  • New Features

    • Added ASIO buffer sequence compatibility adapters for improved interoperability with asynchronous I/O operations.
    • Added conditional mimalloc memory allocation support for shared library builds.
  • Refactor

    • Simplified buffer class structure by removing internal inheritance layers.
    • Renamed allocator-related APIs to clarify frame allocator semantics throughout the coroutine framework.
  • Chores

    • Reordered build dependencies for improved example compilation sequence.

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

The PR reorders CMake build sequence, refactors buffer class hierarchy by eliminating inheritance, introduces ASIO buffer sequence adaptor, renames coroutine allocator APIs to frame_allocator throughout, conditionalizes mimalloc support based on BUILD_SHARED_LIBS, and updates example code for ASIO buffer compatibility.

Changes

Cohort / File(s) Summary
Build System & Configuration
CMakeLists.txt, example/allocation/CMakeLists.txt
Reorders Examples before Tests; conditionalizes mimalloc FetchContent and linking on BUILD_SHARED_LIBS with new BOOST_CAPY_HAS_MIMALLOC compile definition.
Buffer Class Refactoring
include/boost/capy/buffers.hpp
Removes detail::basic_buffer inheritance; converts mutable_buffer and const_buffer to standalone classes with direct p_/n_ member storage; removes Asio-related constructors; retains public data()/size() interface.
ASIO Integration
include/boost/capy/buffers/asio.hpp, example/asio/api/capy_streams.cpp, example/asio/api/uni_stream.hpp
New buffer_sequence_adaptor for bidirectional Capy↔Asio buffer conversion; adds to_asio() and from_asio() public APIs with is_native_asio_v trait; updates async read/write paths to wrap buffers with capy::to_asio() and capy::from_asio().
Allocator → Frame_Allocator Rename
include/boost/capy/ex/io_env.hpp, include/boost/capy/ex/this_coro.hpp, include/boost/capy/ex/io_awaitable_promise_base.hpp, include/boost/capy/ex/run.hpp, include/boost/capy/task.hpp, include/boost/capy/when_all.hpp, include/boost/capy/when_any.hpp
Systematic rename of allocator_tag → frame_allocator_tag, allocator → frame_allocator across coroutine infrastructure; updates await_transform, io_env member, and TLS restoration logic.
Example Code Updates
example/allocation/allocation.cpp
Wraps mimalloc support with BOOST_CAPY_HAS_MIMALLOC guards; consolidates output formatting via std::ostringstream; conditionally includes mi_memory_resource adapter implementation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

  • Prepare Capy for Review #96: Overlapping refactor of io_awaitable_promise_base and io_env/this_coro coroutine plumbing, including allocator conceptual updates.
  • stuff #156: Complements frame allocator changes with design rationale and documentation updates to thread-local frame allocator semantics.
  • Revise javadoc for all public interfaces #121: Co-modifies include/boost/capy/buffers.hpp buffer class definitions and public interfaces.

Poem

🐰 A rabbit hops through buffers bright,
From ASIO's dance to frame allocator's light,
No more base classes blocking the way,
Adapters and renames make code play!
Direct memory holds the day,
Mimalloc's optional sway! 🎉

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'this and that' is vague and generic, using non-descriptive terms that do not convey meaningful information about the changeset's primary purpose. Replace with a descriptive title that summarizes the main changes, such as 'Refactor buffer API and rename allocator to frame_allocator' or 'Add ASIO buffer integration and conditional mimalloc support'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cppalliance-bot
Copy link

An automated preview of the documentation is available at https://178.capy.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-02-21 03:45:48 UTC

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
include/boost/capy/ex/io_awaitable_promise_base.hpp (1)

29-131: ⚠️ Potential issue | 🟡 Minor

Stale allocator references remain in the class-level documentation.

The rename from allocator to frame_allocator was applied to the code and to the await_transform doc, but four occurrences in the class-level Doxygen block still reference the old name:

Line Current text Should be
42 co_await this_coro::allocator co_await this_coro::frame_allocator
68 env->allocator env->frame_allocator
73 co_await this_coro::allocator co_await this_coro::frame_allocator
128 this_coro::allocator this_coro::frame_allocator
📝 Proposed fix
-       and `co_await this_coro::allocator`.
+       and `co_await this_coro::frame_allocator`.
-        // Access env->executor, env->stop_token, env->allocator
+        // Access env->executor, env->stop_token, env->frame_allocator
-        auto* alloc = co_await this_coro::allocator;
+        auto* alloc = co_await this_coro::frame_allocator;
-    `@see` this_coro::environment, this_coro::executor,
-         this_coro::stop_token, this_coro::allocator
+    `@see` this_coro::environment, this_coro::executor,
+         this_coro::stop_token, this_coro::frame_allocator
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/boost/capy/ex/io_awaitable_promise_base.hpp` around lines 29 - 131,
Update the class-level Doxygen to use the new name "frame_allocator" everywhere
the old "allocator" appears: change `co_await this_coro::allocator` to `co_await
this_coro::frame_allocator`, change occurrences of `env->allocator` to
`env->frame_allocator`, and update the final reference `this_coro::allocator` to
`this_coro::frame_allocator`; search for these exact tokens in the docblock
around the io_awaitable_promise_base comment and replace them so the docs match
the code and await_transform wording.
example/allocation/allocation.cpp (1)

71-77: ⚠️ Potential issue | 🟡 Minor

do_is_equal uses identity comparison but mimalloc uses a global heap

Per [mem.res.private], do_is_equal must return true if and only if memory allocated by *this can safely be deallocated by other. Since all mi_memory_resource instances route through the same global mimalloc heap, cross-instance deallocation is safe and do_is_equal should compare types, not identities.

The current this == &other incorrectly returns false for two separate instances, which can trigger unnecessary copies in PMR containers on move/swap across differently-addressed resources.

🐛 Proposed fix
     bool
     do_is_equal(
         memory_resource const& other) const noexcept override
     {
-        return this == &other;
+        return dynamic_cast<mi_memory_resource const*>(&other) != nullptr;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@example/allocation/allocation.cpp` around lines 71 - 77, The do_is_equal
method currently compares instance identities (this == &other) which is wrong
for mi_memory_resource because all instances share the same global mimalloc
heap; change do_is_equal in the mi_memory_resource-derived class to compare
types instead (e.g., return typeid(*this) == typeid(other) or return
dynamic_cast<const mi_memory_resource*>(&other) != nullptr) so that distinct
instances of the same resource type compare equal and cross-instance
deallocation is allowed.
🧹 Nitpick comments (1)
example/allocation/allocation.cpp (1)

10-30: High-level overview comment should be a /* */ block placed after the includes

The existing //-style overview at lines 10–16 is placed before the #include directives. Per coding guidelines, non-trivial implementation files should have a /* */ block comment after the includes providing the high-level overview.

♻️ Suggested relocation
-//
-// Allocation Example
-//
-// Compares the performance of three frame allocators: the default
-// recycling allocator, mimalloc, and std::allocator (no recycling).
-// A 4-deep coroutine chain is invoked 2 million times with each.
-//
-
 `#include` <boost/capy.hpp>
 `#include` <boost/capy/test/run_blocking.hpp>
 `#if` BOOST_CAPY_HAS_MIMALLOC
 `#include` <mimalloc.h>
 `#endif`
 `#include` <atomic>
 `#include` <chrono>
 `#include` <cmath>
 `#include` <cstddef>
 `#include` <iomanip>
 `#include` <iostream>
 `#include` <memory_resource>
 `#include` <sstream>
+
+/*
+ * Allocation Example
+ *
+ * Compares the performance of three frame allocators: the default
+ * recycling allocator, mimalloc, and std::allocator (no recycling).
+ * A 4-deep coroutine chain is invoked 2 million times with each.
+ * mimalloc support is conditionally compiled via BOOST_CAPY_HAS_MIMALLOC.
+ */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@example/allocation/allocation.cpp` around lines 10 - 30, Convert the
top-of-file // style high-level overview (the "Allocation Example" lines
currently before the `#include` directives) into a /* ... */ block and move it
immediately after the `#include` section; specifically, locate the existing
single-line comments that describe the allocator comparison and coroutine chain
and replace them with a single multi-line block comment placed after the last
`#include`, preserving the original text and formatting so the file-level overview
appears after the includes rather than before them.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CMakeLists.txt`:
- Around line 101-114: The tests assume Boost::asio is provided by building the
example, but BOOST_CAPY_BUILD_EXAMPLES and BOOST_CAPY_BUILD_TESTS are
independent; fix by enforcing the dependency or relocating the discovery: either
add an explicit guard in the root CMakeLists.txt that errors or forces
BOOST_CAPY_BUILD_EXAMPLES=ON when BOOST_CAPY_BUILD_TESTS is ON (referencing the
variables BOOST_CAPY_BUILD_EXAMPLES and BOOST_CAPY_BUILD_TESTS), or move the
Boost::asio discovery (find_package(Boost COMPONENTS asio) / find_package(Boost
REQUIRED COMPONENTS asio)) into the test CMakeLists (e.g.,
test/unit/CMakeLists.txt) or the root so tests directly find and link
Boost::asio without relying on the example target; implement one of these
options and update test/unit/CMakeLists.txt to link to Boost::asio
unconditionally when tests are enabled.

In `@example/allocation/CMakeLists.txt`:
- Around line 10-18: Add a short clarifying comment above the conditional that
fetches and links mimalloc explaining why the mimalloc arm is gated on
BUILD_SHARED_LIBS (e.g., to avoid ODR/multiple allocator-instance issues when
Boost::capy is built SHARED, or because the static build should not include the
mimalloc benchmark), and state whether this is intentional or should instead be
inverted to NOT BUILD_SHARED_LIBS; reference the BUILD_SHARED_LIBS symbol and
the mimalloc / mimalloc-static linkage to make the intent clear relative to
Boost::capy and the benchmark behavior.

In `@include/boost/capy/buffers/asio.hpp`:
- Around line 303-306: The constraint on the from_asio template is too broad
because the second disjunct allows any bidirectional range (e.g.,
std::vector<int>), causing hard errors instead of SFINAE-failure; tighten the
concept to require that the range's value type is convertible to
asio::const_buffer (or that the range is a range_of/asio::const_buffer), i.e.
replace the plain std::ranges::bidirectional_range<std::remove_cvref_t<BS>> with
a conjunction that also requires
std::convertible_to<std::ranges::range_value_t<std::remove_cvref_t<BS>>,
asio::const_buffer> (or the equivalent range_of/asio::const_buffer trait) so
from_asio only participates in overload resolution when elements are
buffer-like.

---

Outside diff comments:
In `@example/allocation/allocation.cpp`:
- Around line 71-77: The do_is_equal method currently compares instance
identities (this == &other) which is wrong for mi_memory_resource because all
instances share the same global mimalloc heap; change do_is_equal in the
mi_memory_resource-derived class to compare types instead (e.g., return
typeid(*this) == typeid(other) or return dynamic_cast<const
mi_memory_resource*>(&other) != nullptr) so that distinct instances of the same
resource type compare equal and cross-instance deallocation is allowed.

In `@include/boost/capy/ex/io_awaitable_promise_base.hpp`:
- Around line 29-131: Update the class-level Doxygen to use the new name
"frame_allocator" everywhere the old "allocator" appears: change `co_await
this_coro::allocator` to `co_await this_coro::frame_allocator`, change
occurrences of `env->allocator` to `env->frame_allocator`, and update the final
reference `this_coro::allocator` to `this_coro::frame_allocator`; search for
these exact tokens in the docblock around the io_awaitable_promise_base comment
and replace them so the docs match the code and await_transform wording.

---

Nitpick comments:
In `@example/allocation/allocation.cpp`:
- Around line 10-30: Convert the top-of-file // style high-level overview (the
"Allocation Example" lines currently before the `#include` directives) into a /*
... */ block and move it immediately after the `#include` section; specifically,
locate the existing single-line comments that describe the allocator comparison
and coroutine chain and replace them with a single multi-line block comment
placed after the last `#include`, preserving the original text and formatting so
the file-level overview appears after the includes rather than before them.

Comment on lines +101 to +114
# Examples (before tests so Boost::asio is available)
#
#-------------------------------------------------
if (BOOST_CAPY_BUILD_TESTS)
add_subdirectory(test)
if (BOOST_CAPY_BUILD_EXAMPLES)
add_subdirectory(example)
endif ()

#-------------------------------------------------
#
# Examples
# Tests
#
#-------------------------------------------------
if (BOOST_CAPY_BUILD_EXAMPLES)
add_subdirectory(example)
if (BOOST_CAPY_BUILD_TESTS)
add_subdirectory(test)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -e txt CMakeLists.txt --exec grep -l -i "asio\|Boost::asio" {}

Repository: cppalliance/capy

Length of output: 158


🏁 Script executed:

# Also search more broadly for find_package and FetchContent related to Boost
rg -i "(find_package|FetchContent).*[Bb]oost|[Bb]oost.*asio" --type cmake

Repository: cppalliance/capy

Length of output: 1360


🏁 Script executed:

# Check the content of test/CMakeLists.txt and example/CMakeLists.txt specifically
echo "=== Checking test/CMakeLists.txt ===" && \
cat test/CMakeLists.txt 2>/dev/null | head -50 && \
echo "=== Checking example/CMakeLists.txt ===" && \
cat example/CMakeLists.txt 2>/dev/null | head -50

Repository: cppalliance/capy

Length of output: 1306


🏁 Script executed:

cat CMakeLists.txt | head -120 | tail -30

Repository: cppalliance/capy

Length of output: 840


🏁 Script executed:

# Check if there's any find_package for Boost at root level before examples
rg "find_package|FetchContent" CMakeLists.txt -B2 -A2 | head -60

Repository: cppalliance/capy

Length of output: 42


Implicit Boost::asio availability dependency is not enforced

The comment states tests depend on examples being built first to make Boost::asio available, but both are independently guarded. If BOOST_CAPY_BUILD_EXAMPLES=OFF and BOOST_CAPY_BUILD_TESTS=ON (a common CI configuration), tests will be configured without Boost::asio, causing a silent failure—tests compile but the conditional link against Boost::asio (in test/unit/CMakeLists.txt) is skipped since the target is never created.

Consider either:

  1. Adding an explicit CMake guard, or
  2. Moving the Boost::asio discovery into the test CMakeLists.txt (or the root) rather than relying on examples as a side-effect.
🛡️ Suggested guard
+if (BOOST_CAPY_BUILD_TESTS AND NOT BOOST_CAPY_BUILD_EXAMPLES)
+    message(FATAL_ERROR
+        "BOOST_CAPY_BUILD_TESTS requires BOOST_CAPY_BUILD_EXAMPLES "
+        "(or a standalone Boost::asio discovery in test/CMakeLists.txt)")
+endif()
+
 `#-------------------------------------------------`
 #
 # Examples (before tests so Boost::asio is available)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CMakeLists.txt` around lines 101 - 114, The tests assume Boost::asio is
provided by building the example, but BOOST_CAPY_BUILD_EXAMPLES and
BOOST_CAPY_BUILD_TESTS are independent; fix by enforcing the dependency or
relocating the discovery: either add an explicit guard in the root
CMakeLists.txt that errors or forces BOOST_CAPY_BUILD_EXAMPLES=ON when
BOOST_CAPY_BUILD_TESTS is ON (referencing the variables
BOOST_CAPY_BUILD_EXAMPLES and BOOST_CAPY_BUILD_TESTS), or move the Boost::asio
discovery (find_package(Boost COMPONENTS asio) / find_package(Boost REQUIRED
COMPONENTS asio)) into the test CMakeLists (e.g., test/unit/CMakeLists.txt) or
the root so tests directly find and link Boost::asio without relying on the
example target; implement one of these options and update
test/unit/CMakeLists.txt to link to Boost::asio unconditionally when tests are
enabled.

Comment on lines +10 to +18
if(BUILD_SHARED_LIBS)
include(FetchContent)
FetchContent_Declare(mimalloc
GIT_REPOSITORY https://github.com/microsoft/mimalloc
GIT_TAG v2.2.7
GIT_SHALLOW TRUE)
set(MI_BUILD_TESTS OFF CACHE BOOL "Disable mimalloc tests" FORCE)
FetchContent_MakeAvailable(mimalloc)
endif()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for BUILD_SHARED_LIBS usage in CMakeLists.txt files
rg -n "BUILD_SHARED_LIBS" --include="CMakeLists.txt" -A2 -B2

Repository: cppalliance/capy

Length of output: 501


🏁 Script executed:

#!/bin/bash
# Read the full example/allocation/CMakeLists.txt file to understand context
cat example/allocation/CMakeLists.txt

Repository: cppalliance/capy

Length of output: 1186


🏁 Script executed:

#!/bin/bash
# Search for mimalloc-related configuration or comments
rg -n "mimalloc" --include="CMakeLists.txt" -B2 -A2

Repository: cppalliance/capy

Length of output: 501


🏁 Script executed:

#!/bin/bash
# Search for BUILD_SHARED_LIBS patterns in CMakeLists.txt files with corrected syntax
fd CMakeLists.txt -x rg "BUILD_SHARED_LIBS" {} -B2 -A2

Repository: cppalliance/capy

Length of output: 633


🏁 Script executed:

#!/bin/bash
# Check the root CMakeLists.txt for any related configuration
cat CMakeLists.txt

Repository: cppalliance/capy

Length of output: 4087


🏁 Script executed:

#!/bin/bash
# Search for any comments or documentation about allocator strategy
rg "mimalloc" -B3 -A3

Repository: cppalliance/capy

Length of output: 5915


Add clarifying comment explaining the BUILD_SHARED_LIBS condition for mimalloc

The mimalloc setup (lines 10–18) and linking of mimalloc-static (lines 31–35) are both gated on BUILD_SHARED_LIBS=ON. This is counterintuitive: BUILD_SHARED_LIBS controls whether Boost::capy is built as a SHARED or STATIC library, and linking a static allocator specifically when using shared libraries—while omitting the mimalloc arm of the benchmark in the static build—needs explanation.

Add a comment clarifying the design intent: e.g., whether this avoids ODR/allocator-instance issues when Boost::capy is shared, or whether the condition should be inverted to NOT BUILD_SHARED_LIBS.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@example/allocation/CMakeLists.txt` around lines 10 - 18, Add a short
clarifying comment above the conditional that fetches and links mimalloc
explaining why the mimalloc arm is gated on BUILD_SHARED_LIBS (e.g., to avoid
ODR/multiple allocator-instance issues when Boost::capy is built SHARED, or
because the static build should not include the mimalloc benchmark), and state
whether this is intentional or should instead be inverted to NOT
BUILD_SHARED_LIBS; reference the BUILD_SHARED_LIBS symbol and the mimalloc /
mimalloc-static linkage to make the intent clear relative to Boost::capy and the
benchmark behavior.

Comment on lines +303 to +306
template<class BS>
requires std::is_convertible_v<
std::remove_cvref_t<BS>, asio::const_buffer> ||
std::ranges::bidirectional_range<std::remove_cvref_t<BS>>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

from_asio constraint is too permissive — accepts any bidirectional range.

The second disjunct std::ranges::bidirectional_range<std::remove_cvref_t<BS>> doesn't verify that the range's element type is an asio buffer. A std::vector<int> satisfies this constraint and will produce a hard error inside the function body rather than a clean SFINAE/concept failure. Consider tightening, e.g.:

Proposed fix
 template<class BS>
     requires std::is_convertible_v<
         std::remove_cvref_t<BS>, asio::const_buffer> ||
-        std::ranges::bidirectional_range<std::remove_cvref_t<BS>>
+        (std::ranges::bidirectional_range<std::remove_cvref_t<BS>> &&
+         std::is_convertible_v<
+            std::ranges::range_value_t<std::remove_cvref_t<BS>>,
+            asio::const_buffer>)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/boost/capy/buffers/asio.hpp` around lines 303 - 306, The constraint
on the from_asio template is too broad because the second disjunct allows any
bidirectional range (e.g., std::vector<int>), causing hard errors instead of
SFINAE-failure; tighten the concept to require that the range's value type is
convertible to asio::const_buffer (or that the range is a
range_of/asio::const_buffer), i.e. replace the plain
std::ranges::bidirectional_range<std::remove_cvref_t<BS>> with a conjunction
that also requires
std::convertible_to<std::ranges::range_value_t<std::remove_cvref_t<BS>>,
asio::const_buffer> (or the equivalent range_of/asio::const_buffer trait) so
from_asio only participates in overload resolution when elements are
buffer-like.

@cppalliance-bot
Copy link

GCOVR code coverage report https://178.capy.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://178.capy.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://178.capy.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-02-21 03:58:31 UTC

@vinniefalco vinniefalco merged commit f3faef3 into cppalliance:develop Feb 21, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants