GuardedAllocator that can detect heap overflows in a thread-safe manner.
This class takes a BlockAllocator and manages concurrent access to it. This allows a background thread to validate allocations using one of two key methods:
ValidateOne will validate a single block each time it is called. Successive calls will eventually iterate over all blocks.ValidateAll vill validate all current blocks. Other allocator methods will block until the validation is complete.Both methods can be called explicitly, or used to create a thread that periodically validates, e.g.
Note that while this allocator wraps a BlockAllocator it is NOT a block allocator itself. In particular, pointers allocated from this allocator MUST NOT be passed to methods like BlockType::FromUsableSpace.
Public Types | |
| using | BlockType = typename BlockAllocatorType::BlockType |
Public Types inherited from pw::Deallocator | |
| using | Capabilities = allocator::Capabilities |
| using | Capability = allocator::Capability |
| using | Layout = allocator::Layout |
Public Member Functions | |
| constexpr | GuardedAllocator (BlockAllocatorType &allocator) |
| void * | ValidateOne () |
| void * | ValidateAll () |
Public Member Functions inherited from pw::Allocator | |
| void * | Allocate (Layout layout) |
| template<typename T , int &... kExplicitGuard, typename... Args> | |
| std::enable_if_t<!std::is_array_v< T >, 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 , int &... kExplicitGuard, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| UniquePtr< T > | MakeUnique (size_t size) |
| template<typename T , int &... kExplicitGuard, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| UniquePtr< T > | MakeUnique (size_t size, size_t alignment) |
| template<typename T , int &... kExplicitGuard, 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 , int &... kExplicitGuard, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| SharedPtr< T > | MakeShared (size_t size) |
| template<typename T , int &... kExplicitGuard, std::enable_if_t< is_unbounded_array_v< T >, int > = 0> | |
| SharedPtr< T > | MakeShared (size_t size, size_t alignment) |
| template<typename T , int &... kExplicitGuard, 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< allocator::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) |
| 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) |
Private Member Functions | |
| void * | DoAllocate (Layout layout) override |
| void | DoDeallocate (void *ptr) override |
| bool | DoResize (void *ptr, size_t new_size) override |
| Result< Layout > | DoGetInfo (InfoType info_type, const void *ptr) const override |
Additional Inherited Members | |
Protected Member Functions inherited from pw::allocator::internal::GenericGuardedAllocator | |
| constexpr | GenericGuardedAllocator (const Capabilities &capabilities) |
Protected Member Functions inherited from pw::Allocator | |
| constexpr | Allocator ()=default |
| TODO(b/326509341): Remove when downstream consumers migrate. | |
| constexpr | Allocator (const Capabilities &capabilities) |
| virtual std::optional< allocator::Fragmentation > | DoMeasureFragmentation () const |
Protected Member Functions inherited from pw::Deallocator | |
| constexpr | Deallocator ()=default |
| TODO(b/326509341): Remove when downstream consumers migrate. | |
| constexpr | Deallocator (const Capabilities &capabilities) |
Static Protected Member Functions inherited from pw::allocator::internal::GenericGuardedAllocator | |
| static Layout | AdjustLayout (Layout layout) |
| static size_t | AdjustSize (void *ptr, size_t inner_size) |
| static void * | GetOriginal (void *ptr) |
| static void * | AddPrefix (void *ptr, size_t alignment) |
| static void | AddSuffix (void *ptr, size_t size) |
Adds a suffix a the end of the allocation given by ptr and size. | |
| static bool | CheckPrefixAndSuffix (void *ptr, size_t size) |
Static Protected Attributes inherited from pw::Deallocator | |
| template<typename T > | |
| static constexpr bool | is_bounded_array_v |
| template<typename T > | |
| static constexpr bool | is_unbounded_array_v |
|
overrideprivatevirtual |
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. |
Implements pw::Allocator.
|
overrideprivate |
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. |
|
overrideprivate |
|
overrideprivatevirtual |
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.
| void * pw::allocator::GuardedAllocator< BlockAllocatorType, LockType >::ValidateAll |
Checks for heap overflows in all current allocations.
This method may be called explicitly, or repeatedly from a background thread. Other allocator methods will block until the validation is complete.
| void * pw::allocator::GuardedAllocator< BlockAllocatorType, LockType >::ValidateOne |
Checks for heap overflows in an allocation.
This method may be called explicitly, or repeatedly from a background thread. The individual allocation being checked is not specified, but repeated calls will eventually iterate over all blocks.