An allocator that can "frame" its allocation with a leading prefix type, a trailing suffix type, or both.
At least one of Prefix and Suffix must be a type other than void, since in that case there is no need for a frame.
In addition to the template parameter types, each allocation will include up to three additional size_t fields.
void. When present, this field is located just before the usable memory.void, or at the start of the frame.void, or just before the usable memory.The frame offset and data offset locations may match, i.e. the field just after the prefix is right before the suffix offset or usable memory. In this case, only one offset is stored as both the frame and data offset.
Thus assuming sizeof(size_t) == 4, requesting a 64-byte allocation with a 16-byte alignment from a FramingAllocator<uint32_t, uint16_t> might result in an allocation that looks like:
Alternatively, if the selected memory for the same allocation happens to start at 0x...04, the prefix offsets will be combined:
Let's drop the suffix for simplicity. If we make a similar allocation from a FramingAllocator<uint32_t, void> that happens to start at 0x...0C, we get the worst case scenario for padding to maintain alignment:
Finally, requesting a 64-byte allocation with a 16-byte alignment from a suffix-only FramingAllocator<void, uint16_t> might result in an allocation that looks like:
Suffix and the allocated data both have an alignment of alignof(size_t) or less.| Prefix | A default constructible and trivially copyable type to place before each allocation, or void. alignof(Prefix) must be at most alignof(size_t). |
| Suffix | A default constructible and trivially copyable type to place after each allocation, or void. |
Protected Member Functions | |
| constexpr | FramingAllocator (Allocator &allocator) |
| void * | DoAllocate (Layout layout) override |
| void | DoDeallocate (void *ptr) override |
| bool | DoResize (void *ptr, size_t new_size) override |
| void | DoBeforeReallocate (void *ptr, Layout new_layout) override |
| void | DoAfterReallocateCopy (void *ptr, Layout new_layout, void *new_ptr) override |
| Result< Layout > | DoGetInfo (InfoType info_type, const void *ptr) const override |
| bool | IsValid (const void *data) const |
| void * | GetFrame (const void *data) const |
| Prefix * | GetPrefix (void *data) const |
Protected Member Functions inherited from pw::allocator::internal::BaseFramingAllocator | |
| constexpr | BaseFramingAllocator (Allocator &allocator) |
Protected Member Functions inherited from pw::allocator::ForwardingAllocator | |
| constexpr | ForwardingAllocator (const Capabilities &capabilities) noexcept |
| constexpr | ForwardingAllocator (pw::Allocator &allocator) noexcept |
| constexpr void | Init (pw::Allocator &allocator) |
| constexpr pw::Allocator & | allocator () |
| constexpr const pw::Allocator & | allocator () const |
| void * | DoAllocate (Layout layout) override |
| void | DoDeallocate (void *ptr) override |
| bool | DoResize (void *ptr, size_t new_size) override |
| void | DoBeforeReallocate (void *ptr, Layout new_layout) override |
| void | DoAfterReallocateCopy (void *ptr, Layout new_layout, void *new_ptr) override |
| void | DoAfterReallocateDone (Layout new_layout, void *new_ptr) override |
| size_t | DoGetAllocated () const override |
| std::optional< Fragmentation > | DoMeasureFragmentation () const override |
| Returns fragmentation information for the allocator's memory region. | |
| Result< Layout > | DoGetInfo (InfoType info_type, const void *ptr) const override |
Protected Member Functions inherited from pw::Allocator | |
| constexpr | Allocator () noexcept=default |
| TODO(b/326509341): Remove when downstream consumers migrate. | |
| constexpr | Allocator (const Capabilities &capabilities) noexcept |
| virtual void * | DoAllocate (Layout layout)=0 |
| virtual bool | DoResize (void *ptr, size_t new_size) |
| virtual void * | DoReallocate (void *ptr, Layout new_layout) |
| virtual void | DoBeforeReallocate (void *ptr, Layout new_layout) |
| virtual void | DoAfterReallocateCopy (void *ptr, Layout new_layout, void *new_ptr) |
| virtual void | DoAfterReallocateDone (Layout new_layout, void *new_ptr) |
| virtual size_t | DoGetAllocated () const |
| virtual std::optional< Fragmentation > | DoMeasureFragmentation () const |
| Returns fragmentation information for the allocator's memory region. | |
Protected Member Functions inherited from pw::Deallocator | |
| constexpr | Deallocator ()=default |
| TODO(b/326509341): Remove when downstream consumers migrate. | |
| constexpr | Deallocator (const Capabilities &capabilities) |
| Result< Layout > | GetInfo (InfoType info_type, const void *ptr) const |
| Result< Layout > | GetRequestedLayout (const void *ptr) const |
| Result< Layout > | GetUsableLayout (const void *ptr) const |
| Result< Layout > | GetAllocatedLayout (const void *ptr) const |
| bool | Recognizes (const void *ptr) const |
| virtual void | DoDeallocate (void *ptr)=0 |
| virtual Result< Layout > | DoGetInfo (InfoType, const void *) const |
Static Protected Member Functions | |
| static constexpr Layout | GetFrameLayout (Layout layout) |
| static void * | GetData (void *frame) |
| Returns a data pointer from a frame pointer. | |
| static Suffix * | GetSuffix (void *data) |
Static Protected Member Functions inherited from pw::allocator::internal::BaseFramingAllocator | |
| static bool | CrashOnUnalignedIfStrict (bool strict, const void *data) |
| static bool | CrashOnBadDataIfStrict (bool strict, const void *data) |
| static bool | CrashOnBadPrefixOffsetIfStrict (bool strict, const void *data, size_t prefix_offset, size_t min_size=0) |
| static bool | CrashOnWrongPrefixOffsetIfStrict (bool strict, const void *data, size_t data_prefix_offset, const void *frame, size_t frame_prefix_offset) |
| static bool | CrashOnBadSuffixOffsetIfStrict (bool strict, const void *data, size_t suffix_offset, size_t usable_size) |
| static bool | CrashOnUnrecognized (bool strict, const void *frame) |
Static Protected Member Functions inherited from pw::Allocator | |
| static void | BeforeReallocate (Allocator &allocator, void *ptr, Layout new_layout) |
| static void | AfterReallocateCopy (Allocator &allocator, void *ptr, Layout new_layout, void *new_ptr) |
| static void | AfterReallocateDone (Allocator &allocator, Layout new_layout, void *new_ptr) |
Static Protected Member Functions inherited from pw::Deallocator | |
| static Result< Layout > | GetInfo (const Deallocator &deallocator, InfoType info_type, const void *ptr) |
| static Result< Layout > | GetRequestedLayout (const Deallocator &deallocator, const void *ptr) |
| static Result< Layout > | GetUsableLayout (const Deallocator &deallocator, const void *ptr) |
| static Result< Layout > | GetAllocatedLayout (const Deallocator &deallocator, const void *ptr) |
| static bool | Recognizes (const Deallocator &deallocator, const void *ptr) |
Additional Inherited Members | |
Public Types inherited from pw::Allocator | |
| using | Fragmentation = allocator::Fragmentation |
Public Types inherited from pw::Deallocator | |
| using | Capabilities = allocator::Capabilities |
| using | Capability = allocator::Capability |
| using | Layout = allocator::Layout |
Public Member Functions inherited from pw::Allocator | |
| void * | Allocate (Layout layout) |
| template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0, typename... Args> | |
| T * | New (Args &&... args) |
| template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_bounded_array_v< T >, int > = 0> | |
| ElementType * | New () |
| template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| ElementType * | New (size_t count) |
| template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| ElementType * | New (size_t count, size_t alignment) |
Constructs an alignment-byte aligned array of count objects. | |
| template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0, typename... Args> | |
| UniquePtr< T > | MakeUnique (Args &&... args) |
| template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| UniquePtr< T > | MakeUnique (size_t size) |
| template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| UniquePtr< T > | MakeUnique (size_t size, size_t alignment) |
| template<typename T , std::enable_if_t< is_bounded_array_v< T >, int > = 0> | |
| UniquePtr< T > | MakeUnique () |
| template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0, typename... Args> | |
| SharedPtr< T > | MakeShared (Args &&... args) |
| template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| SharedPtr< T > | MakeShared (size_t size) |
| template<typename T , std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| SharedPtr< T > | MakeShared (size_t size, size_t alignment) |
| template<typename T , std::enable_if_t< is_bounded_array_v< T >, int > = 0> | |
| SharedPtr< T > | MakeShared () |
| bool | Resize (void *ptr, size_t new_size) |
| void * | Reallocate (void *ptr, Layout new_layout) |
| size_t | GetAllocated () const |
| std::optional< Fragmentation > | MeasureFragmentation () const |
| Returns fragmentation information for the allocator's memory region. | |
Public Member Functions inherited from pw::Deallocator | |
| constexpr const Capabilities & | capabilities () const |
| constexpr bool | HasCapability (Capability capability) const |
| Returns whether a given capability is enabled for this object. | |
| void | Deallocate (void *ptr) |
| template<typename ElementType > | |
| void | DeleteArray (ElementType *ptr, size_t count) |
| template<typename ElementType > | |
| void | Destroy (ElementType *ptr, size_t count) |
| StatusWithSize | GetCapacity () const |
| bool | IsEqual (const Deallocator &other) const |
| template<typename T , int &... kExplicitGuard, std::enable_if_t<!std::is_array_v< T >, int > = 0> | |
| void | Delete (T *ptr) |
| template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_bounded_array_v< T >, int > = 0> | |
| void | Delete (ElementType *ptr) |
| template<typename T , int &... kExplicitGuard, typename ElementType = std::remove_extent_t<T>, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| void | Delete (ElementType *ptr, size_t count) |
Protected Types inherited from pw::Deallocator | |
| enum class | InfoType { kRequestedLayoutOf , kUsableLayoutOf , kAllocatedLayoutOf , kCapacity , kRecognizes } |
Static Protected Attributes inherited from pw::Deallocator | |
| template<typename T > | |
| static constexpr bool | is_bounded_array_v = ::pw::is_bounded_array_v<T> |
| template<typename T > | |
| static constexpr bool | is_unbounded_array_v = ::pw::is_unbounded_array_v<T> |
|
overrideprotectedvirtual |
Called as part of the default implementation of DoReallocate once the data from ptr has been resized or copied to new_ptr.
By default, does nothing. Derived types may implement this method to add additional behavior. If they do, they must call DoAfterReallocateCopy on their base type before performing any other action.
ptr and new_ptr are guaranteed to be non-null, and new_layout.size() is guaranteed to be non-zero.
Reimplemented from pw::allocator::ForwardingAllocator.
|
overrideprotectedvirtual |
Allocates a block of memory with the specified size and alignment.
Returns nullptr if the allocation cannot be made, or the layout has a size of 0.
| [in] | layout | Describes the memory to be allocated. |
Reimplemented from pw::allocator::ForwardingAllocator.
|
overrideprotectedvirtual |
Called at the start of the default implementation of DoReallocate.
By default, does nothing. Derived types may implement this method to add additional behavior. If they do, they must call DoBeforeReallocate on their base type just before returning.
ptr is guaranteed to be non-null, and new_layout.size() is guaranteed to be non-zero.
Reimplemented from pw::allocator::ForwardingAllocator.
|
overrideprotectedvirtual |
Releases a previously-allocated block of memory.
The given pointer must have been previously provided by this memory resource; otherwise the behavior is undefined.
| [in] | ptr | Pointer to previously-allocated memory. |
Reimplemented from pw::allocator::ForwardingAllocator.
|
overrideprotectedvirtual |
Returns deallocator-specific information about allocations.
Deallocators may support any number of InfoTypes. See that type for what each supported type returns. For unsupported types, this method returns UNIMPLEMENTED.
Reimplemented from pw::allocator::ForwardingAllocator.
|
overrideprotectedvirtual |
Modifies the size of an previously-allocated block of memory without copying any data.
Returns true if its size was changed without copying data to a new allocation; otherwise returns false.
In particular, it always returns true if the old_layout.size() equals new_size, and always returns false if the given pointer is null, the old_layout.size() is 0, or the new_size is 0.
| [in] | ptr | Pointer to previously-allocated memory. |
| [in] | new_size | Requested new size for the memory allocation. |
Reimplemented from pw::allocator::ForwardingAllocator.
|
protected |
Returns the frame pointer from a data pointer, that is, return a pointer to memory holding the prefix, usable memory, and suffix from a pointer to the usable memory.
|
staticconstexprprotected |
Returns the result of framing the given layout with a prefix and suffix.
This is conservative and pessimistic; the returned layout is always large enough for framing to succeed. Methods like DoAllocatewill free extra memory that isn't needed.
|
protected |
Returns a pointer to prefix.
It is an error to call this method if the prefix type is void.
|
staticprotected |
Returns a pointer to the suffix.
It is an error to call this method if the suffix type is void.
|
protected |
Returns whether the given data pointer correspond to a valid frame from this allocator. If strict is true, does not return when invalid and