The Gaudi Framework  master (ff829712)
Loading...
Searching...
No Matches
Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator > Class Template Reference

A fast memory arena that does not track deallocations. More...

#include </builds/gaudi/Gaudi/GaudiKernel/include/Gaudi/Arena/Monotonic.h>

Public Member Functions

 Monotonic (std::size_t next_block_size) noexcept
 Construct an arena whose first block have approximately the given size.
 
 ~Monotonic () noexcept
 
 Monotonic (Monotonic &&)=delete
 
 Monotonic (Monotonic const &)=delete
 
Monotonicoperator= (Monotonic &&)=delete
 
Monotonicoperator= (Monotonic const &)=delete
 
template<std::size_t ReqAlign>
std::byte * allocate (std::size_t n)
 Return an aligned point to n bytes of memory.
 
constexpr void deallocate (std::byte *, std::size_t) noexcept
 Deallocations are not tracked, so this is a no-op!
 
void reset () noexcept
 Signal that this arena may start re-using the memory resources.
 
std::size_t capacity () const noexcept
 Query how much memory is owned by this arena, in bytes.
 
std::size_t size () const noexcept
 Query how much memory was used from this arena, in bytes.
 
std::size_t num_blocks () const noexcept
 Query how many blocks of memory this arena owns.
 
std::size_t num_allocations () const noexcept
 Query how many allocations this arena has served.
 

Static Public Attributes

static constexpr std::size_t alignment = Alignment
 

Private Attributes

std::size_t m_next_block_size {}
 Size (in bytes) of the next block to be allocated.
 
std::size_t m_allocations { 0 }
 Number of allocation requests served by this arena.
 
std::byte * m_current { nullptr }
 Current position in the current block, or nullptr if there is no current block.
 
std::byte * m_current_end { nullptr }
 One byte past the end of the current block, or nullptr if it doesn't exist.
 
boost::container::small_vector< gsl::span< std::byte >, 1 > m_all_blocks
 All memory blocks owned by this arena.
 

Static Private Attributes

static constexpr std::size_t growth_factor = 2
 Approximate factor by which each block is larger than its predecessor.
 

Detailed Description

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
class Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >

A fast memory arena that does not track deallocations.

This is a memory arena suitable for use with Gaudi::Allocators::Arena. It allocates memory from an upstream resource in blocks of geometrically increasing size and serves allocation requests from those blocks. Deallocations are not tracked, so the memory footprint of a Monotonic arena increases monotonically until either it is destroyed or its reset() method is called. All requests are served with alignment specified in the template parameter.

Todo

Efficiently support stateful upstream allocators, probably by putting an instance of the upstream allocator in a boost::compressed_pair.

Use the given UpstreamAllocator to serve dynamic allocations required by boost::container::small_vector.

Definition at line 46 of file Monotonic.h.

Constructor & Destructor Documentation

◆ Monotonic() [1/3]

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::Monotonic ( std::size_t next_block_size)
inlinenoexcept

Construct an arena whose first block have approximately the given size.

This constructor does not trigger any allocation.

Definition at line 74 of file Monotonic.h.

A fast memory arena that does not track deallocations.
Definition Monotonic.h:46
std::size_t m_next_block_size
Size (in bytes) of the next block to be allocated.
Definition Monotonic.h:51
constexpr std::size_t align_up(std::size_t n)
Definition Monotonic.h:24

◆ ~Monotonic()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::~Monotonic ( )
inlinenoexcept

Definition at line 77 of file Monotonic.h.

77 {
78 for ( auto block : m_all_blocks ) { UpstreamAllocator{}.deallocate( block.data(), block.size() ); }
79 }
boost::container::small_vector< gsl::span< std::byte >, 1 > m_all_blocks
All memory blocks owned by this arena.
Definition Monotonic.h:63
std::size_t size() const noexcept
Query how much memory was used from this arena, in bytes.
Definition Monotonic.h:152
constexpr void deallocate(std::byte *, std::size_t) noexcept
Deallocations are not tracked, so this is a no-op!
Definition Monotonic.h:117

◆ Monotonic() [2/3]

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::Monotonic ( Monotonic< Alignment, UpstreamAllocator > && )
delete

◆ Monotonic() [3/3]

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::Monotonic ( Monotonic< Alignment, UpstreamAllocator > const & )
delete

Member Function Documentation

◆ allocate()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
template<std::size_t ReqAlign>
std::byte * Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::allocate ( std::size_t n)
inline

Return an aligned point to n bytes of memory.

This may trigger allocation from the upstream resource.

Definition at line 92 of file Monotonic.h.

92 {
93 // If the requested alignment was larger we would need to round up
94 // m_current -- instead of implementing that, just assert it's not
95 // the case.
96 static_assert( ReqAlign <= alignment, "Requested alignment too large for this Gaudi::Arena::Monotonic!" );
97 // Figure out how many bytes we need to allocate
99 // Check that we have a current block and this request fits inside it
101 // Calculate our next block size
103 // And update the estimate of what comes after that, following a geometric series
105 // Allocate the new block and mark it as the current one
108 // Add it to the list of blocks that we'll eventually deallocate
109 m_all_blocks.emplace_back( m_current, next_block_size );
110 }
113 }
std::byte * m_current_end
One byte past the end of the current block, or nullptr if it doesn't exist.
Definition Monotonic.h:60
std::byte * m_current
Current position in the current block, or nullptr if there is no current block.
Definition Monotonic.h:57
static constexpr std::size_t alignment
Definition Monotonic.h:69
static constexpr std::size_t growth_factor
Approximate factor by which each block is larger than its predecessor.
Definition Monotonic.h:66
std::size_t m_allocations
Number of allocation requests served by this arena.
Definition Monotonic.h:54
std::byte * allocate(std::size_t n)
Return an aligned point to n bytes of memory.
Definition Monotonic.h:92

◆ capacity()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::capacity ( ) const
inlinenodiscardnoexcept

Query how much memory is owned by this arena, in bytes.

Definition at line 145 of file Monotonic.h.

145 {
146 return std::accumulate( m_all_blocks.begin(), m_all_blocks.end(), 0ul,
147 []( std::size_t sum, auto block ) { return sum + block.size(); } );
148 }

◆ deallocate()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
void Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::deallocate ( std::byte * ,
std::size_t  )
inlineconstexprnoexcept

Deallocations are not tracked, so this is a no-op!

Definition at line 117 of file Monotonic.h.

117{}

◆ num_allocations()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::num_allocations ( ) const
inlinenodiscardnoexcept

Query how many allocations this arena has served.

Definition at line 160 of file Monotonic.h.

160{ return m_allocations; }

◆ num_blocks()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::num_blocks ( ) const
inlinenodiscardnoexcept

Query how many blocks of memory this arena owns.

Definition at line 156 of file Monotonic.h.

156{ return m_all_blocks.size(); }

◆ operator=() [1/2]

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
Monotonic & Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::operator= ( Monotonic< Alignment, UpstreamAllocator > && )
delete

◆ operator=() [2/2]

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
Monotonic & Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::operator= ( Monotonic< Alignment, UpstreamAllocator > const & )
delete

◆ reset()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
void Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::reset ( )
inlinenoexcept

Signal that this arena may start re-using the memory resources.

  • If the arena owns zero blocks, there is no change.
  • If the arena owns one block, it will reset to serving future requests from the start of that block.
  • If the arena owns more than one block, it will deallocate all but the first one and serve future requests from the start of the remaining block.

Definition at line 126 of file Monotonic.h.

126 {
127 m_allocations = 0;
128 if ( !m_all_blocks.empty() ) {
129 // Only re-use the first block, deallocate any others
130 if ( m_all_blocks.size() > 1 ) {
131 for ( std::size_t i = 1; i < m_all_blocks.size(); ++i ) {
133 }
134 m_all_blocks.resize( 1 );
135 }
136 auto reused_block = m_all_blocks.front();
137 m_current = reused_block.data();
140 }
141 }

◆ size()

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::size ( ) const
inlinenodiscardnoexcept

Query how much memory was used from this arena, in bytes.

Definition at line 152 of file Monotonic.h.

152{ return capacity() - ( m_current_end - m_current ); }
std::size_t capacity() const noexcept
Query how much memory is owned by this arena, in bytes.
Definition Monotonic.h:145

Member Data Documentation

◆ alignment

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::alignment = Alignment
staticconstexpr

Definition at line 69 of file Monotonic.h.

◆ growth_factor

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::growth_factor = 2
staticconstexprprivate

Approximate factor by which each block is larger than its predecessor.

Definition at line 66 of file Monotonic.h.

◆ m_all_blocks

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
boost::container::small_vector<gsl::span<std::byte>, 1> Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::m_all_blocks
private

All memory blocks owned by this arena.

Definition at line 63 of file Monotonic.h.

◆ m_allocations

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::m_allocations { 0 }
private

Number of allocation requests served by this arena.

Definition at line 54 of file Monotonic.h.

54{ 0 };

◆ m_current

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::byte* Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::m_current { nullptr }
private

Current position in the current block, or nullptr if there is no current block.

Definition at line 57 of file Monotonic.h.

57{ nullptr };

◆ m_current_end

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::byte* Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::m_current_end { nullptr }
private

One byte past the end of the current block, or nullptr if it doesn't exist.

Definition at line 60 of file Monotonic.h.

60{ nullptr };

◆ m_next_block_size

template<std::size_t Alignment = alignof( std::max_align_t ), typename UpstreamAllocator = std::allocator<std::byte>>
std::size_t Gaudi::Arena::Monotonic< Alignment, UpstreamAllocator >::m_next_block_size {}
private

Size (in bytes) of the next block to be allocated.

Definition at line 51 of file Monotonic.h.

51{};

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