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 ------------------------*/
/*--------------------------------------------------------------------------*/