Program Listing for File PoolAllocator.h
↰ Return to documentation for file (ADS/memory/PoolAllocator.h)
/*--------------------------------------------------------------------------*/
/*-------------------------- File PoolAllocator.h --------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/
#ifndef __ADS_PoolAllocator
#define __ADS_PoolAllocator
/* self-identification: #endif constant */
/*--------------------------------------------------------------------------*/
/*------------------------------ INCLUDES ----------------------------------*/
/*--------------------------------------------------------------------------*/
#include "ADS/Contract.h"
#include "ADS/memory/PageHeap.h"
#include <cstddef>
#include <limits>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
/*--------------------------------------------------------------------------*/
/*--------------------------- NAMESPACE ------------------------------------*/
/*--------------------------------------------------------------------------*/
namespace ADS {
namespace detail {
[[nodiscard]] void * poolNew( std::size_t b , std::size_t a );
void poolDelete( void * p , std::size_t b , std::size_t a ) noexcept;
} // end( namespace detail )
/*--------------------------------------------------------------------------*/
/*--------------------------- CLASS PoolResource ---------------------------*/
/*--------------------------------------------------------------------------*/
template< std::size_t M = 256 >
class PoolResource {
static_assert( ( M >= 16 ) && ( M % 16 == 0 ) && ( M <= 4096 ) ,
"the largest class is a multiple of 16 bytes, up to 4096" );
/*--------------------------------------------------------------------------*/
public:
static constexpr std::size_t GRAIN = 8;
static constexpr std::size_t ALIGN = 16;
static constexpr std::size_t MAX = M;
static constexpr std::size_t CLASSES = M / GRAIN;
[[nodiscard]] static constexpr bool pooled( std::size_t b ,
std::size_t a ) {
return( ( b >= 1 ) && ( b <= M ) && ( a <= ALIGN ) );
}
PoolResource( void );
PoolResource( const PoolResource & ) = delete;
PoolResource & operator=( const PoolResource & ) = delete;
~PoolResource() = default;
template< std::size_t b , std::size_t a = alignof( std::max_align_t ) >
[[nodiscard]] void * allocate( void );
template< std::size_t b , std::size_t a = alignof( std::max_align_t ) >
void deallocate( void * p );
[[nodiscard]] void * allocate( std::size_t b ,
std::size_t a = alignof( std::max_align_t )
);
void deallocate( void * p , std::size_t b ,
std::size_t a = alignof( std::max_align_t ) );
[[nodiscard]] std::size_t size( void ) const;
[[nodiscard]] std::size_t bytes( void ) const;
/*--------------------------------------------------------------------------*/
private:
[[nodiscard]] static constexpr std::size_t classOf( std::size_t b ,
std::size_t a ) {
return( ( a > GRAIN ? ( b + 15 ) / 16 * 2 : ( b + 7 ) / 8 ) - 1 );
}
[[nodiscard]] void * take( std::size_t c ) {
if( void * p = f_heap->local( c ) ) [[likely]]
return( p );
return( f_heap->more( c ) );
}
std::unique_ptr< detail::PageHeap< CLASSES > > f_heap;
}; // end( class PoolResource )
/*--------------------------------------------------------------------------*/
/*--------------------------- CLASS PoolAllocator --------------------------*/
/*--------------------------------------------------------------------------*/
template< class T , class R = PoolResource<> >
class PoolAllocator {
/*--------------------------------------------------------------------------*/
public:
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
using is_always_equal = std::false_type;
template< class U >
struct rebind { using other = PoolAllocator< U , R >; };
PoolAllocator( R & r ) noexcept : f_r( &r ) {}
PoolAllocator( void ) noexcept requires requires { R::global(); }
: f_r( &R::global() ) {}
template< class U >
PoolAllocator( const PoolAllocator< U , R > & o ) noexcept
: f_r( o.resource() ) {}
[[nodiscard]] T * allocate( std::size_t n );
void deallocate( T * p , std::size_t n );
[[nodiscard]] R * resource( void ) const noexcept { return( f_r ); }
template< class U >
bool operator==( const PoolAllocator< U , R > & o ) const noexcept {
return( f_r == o.resource() );
}
/*--------------------------------------------------------------------------*/
private:
R * f_r;
}; // end( class PoolAllocator )
/*--------------------------------------------------------------------------*/
} // end( namespace ADS )
/*--------------------------------------------------------------------------*/
/*-------------------------- IMPLEMENTATION --------------------------------*/
/*--------------------------------------------------------------------------*/
#include "ADS/memory/impl/PoolAllocator.tpp"
/*--------------------------------------------------------------------------*/
#endif /* PoolAllocator.h included */
/*--------------------------------------------------------------------------*/
/*------------------------ End File PoolAllocator.h ------------------------*/
/*--------------------------------------------------------------------------*/