Skip to content

Make frame allocators provide only storage - #2376

Merged
ericniebler merged 1 commit into
NVIDIA:mainfrom
ispeters:remove-uses-allocator-construction
Oct 30, 2026
Merged

ericniebler merged 1 commit into
NVIDIA:mainfrom
ispeters:remove-uses-allocator-construction

Conversation

@ispeters

Copy link
Copy Markdown
Contributor

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.

@copy-pr-bot

copy-pr-bot Bot commented Oct 28, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@ispeters
ispeters force-pushed the remove-uses-allocator-construction branch from 5182fdc to a449b1b Compare October 29, 2026 02:31
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
ispeters force-pushed the remove-uses-allocator-construction branch from a449b1b to 7fb9374 Compare October 30, 2026 02:39
@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test 7fb9374

@ericniebler
ericniebler merged commit a3ed29c into NVIDIA:main Oct 30, 2026
36 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