Program Listing for File Arena.h

↰ Return to documentation for file (ADS/memory/Arena.h)

/*--------------------------------------------------------------------------*/
/*------------------------------ File Arena.h ------------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef __ADS_Arena
 #define __ADS_Arena
                      /* self-identification: #endif constant */

/*--------------------------------------------------------------------------*/
/*------------------------------ INCLUDES ----------------------------------*/
/*--------------------------------------------------------------------------*/

#include "ADS/Contract.h"

#include <compare>
#include <cstddef>
#include <iterator>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include <vector>

/*--------------------------------------------------------------------------*/
/*--------------------------- NAMESPACE ------------------------------------*/
/*--------------------------------------------------------------------------*/

namespace ADS {

/*--------------------------------------------------------------------------*/
/*----------------------------- CLASS Arena --------------------------------*/
/*--------------------------------------------------------------------------*/

template< class T , class A = std::allocator< T > >
class Arena {

/*--------------------------------------------------------------------------*/
 public:

 explicit Arena( std::size_t n = std::size_t( 1 ) << 12 ,
                 const A & alloc = A() );

 Arena( const Arena & ) = delete;
 Arena & operator=( const Arena & ) = delete;

 ~Arena();

 template< class... Args >
 T * make( Args &&... args );

 [[nodiscard]] std::size_t size( void ) const;

 [[nodiscard]] std::size_t bytes( void ) const;

/*------------------------- THE STANDARD INTERFACE -------------------------*/

 // the objects made, in the order of make(), random access across the
 // blocks; their addresses do not change, so the iterators stay valid while
 // the arena lives, and a new object only moves the end

 template< bool Const >
 class Iterator {
  using Blocks = T * const *;   // the blocks, never changed through it

  public:
  using iterator_category = std::random_access_iterator_tag;
  using value_type = T;
  using difference_type = std::ptrdiff_t;
  using reference = std::conditional_t< Const , const T & , T & >;
  using pointer = std::conditional_t< Const , const T * , T * >;

  Iterator( void ) = default;
  Iterator( Blocks B , std::size_t n , std::size_t i )
   : f_B( B ) , f_n( n ) , f_i( i ) {}

  template< bool K > requires ( Const && ! K )
  Iterator( const Iterator< K > & o )
   : f_B( o.f_B ) , f_n( o.f_n ) , f_i( o.f_i ) {}

  reference operator*( void ) const { return( ( *this )[ 0 ] ); }
  pointer operator->( void ) const { return( &**this ); }
  reference operator[]( difference_type k ) const {
   const std::size_t j = f_i + std::size_t( k );
   return( f_B[ j / f_n ][ j % f_n ] );
   }

  Iterator & operator++( void ) { ++f_i; return( *this ); }
  Iterator & operator--( void ) { --f_i; return( *this ); }
  Iterator operator++( int ) { auto t = *this; ++f_i; return( t ); }
  Iterator operator--( int ) { auto t = *this; --f_i; return( t ); }
  Iterator & operator+=( difference_type k ) {
   f_i += std::size_t( k );
   return( *this );
   }
  Iterator & operator-=( difference_type k ) {
   f_i -= std::size_t( k );
   return( *this );
   }
  friend Iterator operator+( Iterator a , difference_type k ) {
   return( a += k );
   }
  friend Iterator operator+( difference_type k , Iterator a ) {
   return( a += k );
   }
  friend Iterator operator-( Iterator a , difference_type k ) {
   return( a -= k );
   }
  friend difference_type operator-( const Iterator & a , const Iterator & b ) {
   return( difference_type( a.f_i ) - difference_type( b.f_i ) );
   }
  bool operator==( const Iterator & o ) const { return( f_i == o.f_i ); }
  auto operator<=>( const Iterator & o ) const { return( f_i <=> o.f_i ); }

  private:
  Blocks f_B = nullptr;
  std::size_t f_n = 1 , f_i = 0;

  template< bool > friend class Iterator;
  };

 using value_type = T;
 using size_type = std::size_t;
 using difference_type = std::ptrdiff_t;
 using reference = T &;
 using const_reference = const T &;
 using iterator = Iterator< false >;
 using const_iterator = Iterator< true >;

 [[nodiscard]] iterator begin( void ) {
  return( iterator( f_blocks.data() , f_n , 0 ) );
  }
 [[nodiscard]] iterator end( void ) {
  return( iterator( f_blocks.data() , f_n , f_size ) );
  }
 [[nodiscard]] const_iterator begin( void ) const {
  return( const_iterator( f_blocks.data() , f_n , 0 ) );
  }
 [[nodiscard]] const_iterator end( void ) const {
  return( const_iterator( f_blocks.data() , f_n , f_size ) );
  }
 [[nodiscard]] const_iterator cbegin( void ) const { return( begin() ); }
 [[nodiscard]] const_iterator cend( void ) const { return( end() ); }

/*--------------------------------------------------------------------------*/
 private:

 std::size_t f_n;
 std::size_t f_used = 0;
 std::size_t f_size = 0;
 std::vector< T * > f_blocks;
 A f_alloc;

 };  // end( class Arena )

/*--------------------------------------------------------------------------*/

}  // end( namespace ADS )

/*--------------------------------------------------------------------------*/
/*-------------------------- IMPLEMENTATION --------------------------------*/
/*--------------------------------------------------------------------------*/

#include "ADS/memory/impl/Arena.tpp"

/*--------------------------------------------------------------------------*/

#endif  /* Arena.h included */

/*--------------------------------------------------------------------------*/
/*---------------------------- End File Arena.h ----------------------------*/
/*--------------------------------------------------------------------------*/