Repository navigation
Make frame allocators provide only storage - #2376
Merged
ericniebler merged 1 commit intoOct 30, 2026
Merged
Conversation
ispeters
force-pushed
the
remove-uses-allocator-construction
branch
from
October 29, 2026 02:31
5182fdc to
a449b1b
Compare
An operation state too big for `function`'s inline buffer is allocated from the frame allocator by the `__any` machinery that `function` shares with `exec::any_sender`, which constructs and destroys it with `allocator_traits<...>::construct` and `destroy`. `function` adapts the frame allocator with `__frame_allocator_t`, which for an allocator is the allocator itself, rebound to `std::byte`. So when a `function` declares `get_frame_allocator`, the caller's allocator's own `construct` and `destroy` members, if it has any, are called on `__any`'s wrapper around the operation state. For a memory resource, `__frame_allocator_t` is `polymorphic_allocator` or an equivalent for the resource's concrete type, whose `construct` does uses-allocator construction. A frame allocator should only provide storage for a frame; what's constructed in it, and how, is up to whoever allocated the frame. This diff makes `__frame_allocator_t` declare no `construct` or `destroy` in every case, so `allocator_traits` constructs with `construct_at` and destroys with `destroy_at`: - for an allocator, it's a new `__allocator_adaptor` around the rebound allocator, which allocates and deallocates through it and is `noexcept` where it is; and - for a pointer to `memory_resource` or to a type derived from it, it's the allocator that already handled derived resources, without its `construct` and `destroy`, so a plain `memory_resource *` no longer gives a `polymorphic_allocator`. `any_sender` doesn't use `__frame_allocator_t`, so it's unchanged. The `__frame_allocator_t` tests now check that it never does uses-allocator construction and never calls a delegate allocator's `construct` or `destroy`, and a new `function` test checks that a large operation state is allocated from a declared frame allocator but neither constructed nor destroyed through it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ispeters
force-pushed
the
remove-uses-allocator-construction
branch
from
October 30, 2026 02:39
a449b1b to
7fb9374
Compare
Collaborator
|
/ok to test 7fb9374 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An operation state too big for
function's inline buffer is allocated from the frame allocator by the__anymachinery thatfunctionshares withexec::any_sender, which constructs and destroys it withallocator_traits<...>::constructanddestroy.functionadapts the frame allocator with__frame_allocator_t, which for an allocator is the allocator itself, rebound tostd::byte. So when afunctiondeclaresget_frame_allocator, the caller's allocator's ownconstructanddestroymembers, if it has any, are called on__any's wrapper around the operation state. For a memory resource,__frame_allocator_tispolymorphic_allocatoror an equivalent for the resource's concrete type, whoseconstructdoes uses-allocator construction.A frame allocator should only provide storage for a frame; what's constructed in it, and how, is up to whoever allocated the frame. This diff makes
__frame_allocator_tdeclare noconstructordestroyin every case, soallocator_traitsconstructs withconstruct_atand destroys withdestroy_at:__allocator_adaptoraround the rebound allocator, which allocates and deallocates through it and isnoexceptwhere it is; andmemory_resourceor to a type derived from it, it's the allocator that already handled derived resources, without itsconstructanddestroy, so a plainmemory_resource *no longer gives apolymorphic_allocator.any_senderdoesn't use__frame_allocator_t, so it's unchanged.The
__frame_allocator_ttests now check that it never does uses-allocator construction and never calls a delegate allocator'sconstructordestroy, and a newfunctiontest checks that a large operation state is allocated from a declared frame allocator but neither constructed nor destroyed through it.