Skip to main content
Pigweed's logo Pigweed
  1. Home
  2. Reference
  3. C/C++
  4. pw::allocator::FramingAllocator< Prefix, Suffix > Class Template Reference
Loading...
Searching...
No Matches
pw::allocator::FramingAllocator< Prefix, Suffix > Class Template Reference

Overview

template<typename Prefix, typename Suffix = void>
class pw::allocator::FramingAllocator< Prefix, Suffix >

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.

  • The offset of the suffix field from the data, i.e. from the allocated pointer. This field is omitted if the suffix type is void. When present, this field is located just before the usable memory.
  • The offset of the data from the start of the frame. This field is located just after the prefix, if the prefix type is not void, or at the start of the frame.
  • The offset of the frame from the start of the data. This has the same value as the frame offset, but can be located using only the data pointer. This field is located just before the suffix offset, if the suffix type is not 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:

Address Type Contents Pointed at by:
+---------+-------------+--------------------+--------------------------+
| 0x...00 | Prefix | user-defined | frame |
| | (uint32_t) | | GetFrame(data) |
| | | | GetPrefix(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...04 | size_t | frame_offset =0x10 | GetFrameOffsetPtr(frame) |
+---------+-------------+--------------------+--------------------------+
| 0x...08 | size_t | data_offset =0x10 | GetDataOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...0C | size_t | suffix_offset=0x40 | GetSuffixOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...10 | std::byte[] | usable space | data |
| | | | GetData(frame) |
+---------+-------------+--------------------+--------------------------+
| 0x...50 | Suffix | user-defined | GetSuffix(data) |
| | (uint16_t) | | |
+---------+-------------+--------------------+--------------------------+
void * GetFrame(const void *data) const
Definition: framing_allocator.h:477
static void * GetData(void *frame)
Returns a data pointer from a frame pointer.
Definition: framing_allocator.h:494
Prefix * GetPrefix(void *data) const
Definition: framing_allocator.h:488
static Suffix * GetSuffix(void *data)
Definition: framing_allocator.h:501

Alternatively, if the selected memory for the same allocation happens to start at 0x...04, the prefix offsets will be combined:

Address Type Contents Pointed at by:
+---------+-------------+--------------------+--------------------------+
| 0x...04 | Prefix | user-defined | frame |
| | (uint32_t) | | GetFrame(data) |
| | | | GetPrefix(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...08 | size_t | frame_offset, | GetFrameOffsetPtr(frame) |
| | | data_offset =0x0C | GetDataOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...0C | size_t | suffix_offset=0x40 | GetSuffixOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...10 | std::byte[] | usable space | data |
| | | | GetData(frame) |
+---------+-------------+--------------------+--------------------------+
| 0x...50 | Suffix | user-defined | GetSuffix(data) |
| | (uint16_t) | | |
+---------+-------------+--------------------+--------------------------+

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:

Address Type Contents Pointed at by:
+---------+-------------+--------------------+--------------------------+
| 0x...0C | Prefix | user-defined | frame |
| | (uint32_t) | | GetFrame(data) |
| | | | GetPrefix(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...10 | size_t | frame_offset =0x10 | GetFrameOffsetPtr(frame) |
+---------+-------------+--------------------+--------------------------+
| 0x...14 | N/A | 8 bytes of padding | N/A |
+---------+-------------+--------------------+--------------------------+
| 0x...1C | size_t | data_offset =0x10 | GetDataOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...20 | std::byte[] | usable space | data |
| | | | GetData(frame) |
+---------+-------------+--------------------+--------------------------+

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:

Address Type Contents Pointed at by:
+---------+-------------+--------------------+--------------------------+
| 0x...00 | size_t | frame_offset =0x10 | frame |
| | | | GetFrame(data) |
| | | | GetFrameOffsetPtr(frame) |
+---------+-------------+--------------------+--------------------------+
| 0x...04 | N/A | 4 bytes of padding | N/A |
+---------+-------------+--------------------+--------------------------+
| 0x...08 | size_t | data_offset =0x10 | GetDataOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...0C | size_t | suffix_offset=0x40 | GetSuffixOffsetPtr(data) |
+---------+-------------+--------------------+--------------------------+
| 0x...10 | std::byte[] | usable space | data |
| | | | GetData(frame) |
+---------+-------------+--------------------+--------------------------+
| 0x...50 | Suffix | user-defined | GetSuffix(data) |
| | (uint16_t) | | |
+---------+-------------+--------------------+--------------------------+
Note
As illustrated above, the choice of prefix and suffix types and overall alignment can significantly affect the amount of overhead required. When possible, keep alignment requirements low. Ideally, Suffix and the allocated data both have an alignment of alignof(size_t) or less.
Template Parameters
PrefixA default constructible and trivially copyable type to place before each allocation, or void. alignof(Prefix) must be at most alignof(size_t).
SuffixA default constructible and trivially copyable type to place after each allocation, or void.
Inheritance diagram for pw::allocator::FramingAllocator< Prefix, Suffix >:
pw::allocator::internal::BaseFramingAllocator pw::allocator::ForwardingAllocator pw::Allocator pw::Deallocator

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< LayoutDoGetInfo (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::Allocatorallocator ()
 
constexpr const pw::Allocatorallocator () 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< FragmentationDoMeasureFragmentation () const override
 Returns fragmentation information for the allocator's memory region.
 
Result< LayoutDoGetInfo (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< FragmentationDoMeasureFragmentation () 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< LayoutGetInfo (InfoType info_type, const void *ptr) const
 
Result< LayoutGetRequestedLayout (const void *ptr) const
 
Result< LayoutGetUsableLayout (const void *ptr) const
 
Result< LayoutGetAllocatedLayout (const void *ptr) const
 
bool Recognizes (const void *ptr) const
 
virtual void DoDeallocate (void *ptr)=0
 
virtual Result< LayoutDoGetInfo (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< LayoutGetInfo (const Deallocator &deallocator, InfoType info_type, const void *ptr)
 
static Result< LayoutGetRequestedLayout (const Deallocator &deallocator, const void *ptr)
 
static Result< LayoutGetUsableLayout (const Deallocator &deallocator, const void *ptr)
 
static Result< LayoutGetAllocatedLayout (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< FragmentationMeasureFragmentation () const
 Returns fragmentation information for the allocator's memory region.
 
- Public Member Functions inherited from pw::Deallocator
constexpr const Capabilitiescapabilities () 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>
 

Member Function Documentation

◆ DoAfterReallocateCopy()

template<typename Prefix , typename Suffix >
void pw::allocator::FramingAllocator< Prefix, Suffix >::DoAfterReallocateCopy ( void *  ptr,
Layout  new_layout,
void *  new_ptr 
)
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.

◆ DoAllocate()

template<typename Prefix , typename Suffix >
void * pw::allocator::FramingAllocator< Prefix, Suffix >::DoAllocate ( Layout  layout)
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.

Parameters
[in]layoutDescribes the memory to be allocated.

Reimplemented from pw::allocator::ForwardingAllocator.

◆ DoBeforeReallocate()

template<typename Prefix , typename Suffix >
void pw::allocator::FramingAllocator< Prefix, Suffix >::DoBeforeReallocate ( void *  ptr,
Layout  new_layout 
)
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.

◆ DoDeallocate()

template<typename Prefix , typename Suffix >
void pw::allocator::FramingAllocator< Prefix, Suffix >::DoDeallocate ( void *  ptr)
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.

Parameters
[in]ptrPointer to previously-allocated memory.

Reimplemented from pw::allocator::ForwardingAllocator.

◆ DoGetInfo()

template<typename Prefix , typename Suffix >
Result< Layout > pw::allocator::FramingAllocator< Prefix, Suffix >::DoGetInfo ( InfoType  info_type,
const void *  ptr 
) const
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.

◆ DoResize()

template<typename Prefix , typename Suffix >
bool pw::allocator::FramingAllocator< Prefix, Suffix >::DoResize ( void *  ptr,
size_t  new_size 
)
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.

Parameters
[in]ptrPointer to previously-allocated memory.
[in]new_sizeRequested new size for the memory allocation.

Reimplemented from pw::allocator::ForwardingAllocator.

◆ GetFrame()

template<typename Prefix , typename Suffix >
auto pw::allocator::FramingAllocator< Prefix, Suffix >::GetFrame ( const void *  data) const
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.

◆ GetFrameLayout()

template<typename Prefix , typename Suffix >
constexpr Layout pw::allocator::FramingAllocator< Prefix, Suffix >::GetFrameLayout ( Layout  layout)
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.

◆ GetPrefix()

template<typename Prefix , typename Suffix >
auto pw::allocator::FramingAllocator< Prefix, Suffix >::GetPrefix ( void *  data) const
protected

Returns a pointer to prefix.

It is an error to call this method if the prefix type is void.

◆ GetSuffix()

template<typename Prefix , typename Suffix >
auto pw::allocator::FramingAllocator< Prefix, Suffix >::GetSuffix ( void *  data)
staticprotected

Returns a pointer to the suffix.

It is an error to call this method if the suffix type is void.

◆ IsValid()

template<typename Prefix , typename Suffix >
bool pw::allocator::FramingAllocator< Prefix, Suffix >::IsValid ( const void *  data) const
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


The documentation for this class was generated from the following file: