Program Listing for File ConcurrentPool.h

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

/*--------------------------------------------------------------------------*/
/*------------------------- File ConcurrentPool.h --------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/

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

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

#include "ADS/Contract.h"
#include "ADS/memory/PageHeap.h"
#include "ADS/memory/PoolAllocator.h"

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <new>
#include <thread>
#include <vector>

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

namespace ADS {

/*--------------------------------------------------------------------------*/
/*---------------------- CLASS ConcurrentPoolResource ----------------------*/
/*--------------------------------------------------------------------------*/

template< std::size_t M = 256 >
class ConcurrentPoolResource {

 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;
 static constexpr std::size_t SEGMENT = detail::PageHeap< CLASSES >::SEGMENT;

 [[nodiscard]] static constexpr bool pooled( std::size_t b ,
                                             std::size_t a ) {
  return( ( b >= 1 ) && ( b <= M ) && ( a <= ALIGN ) );
  }

 ConcurrentPoolResource( void );

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

 ~ConcurrentPoolResource();

 [[nodiscard]] static ConcurrentPoolResource & global( void );

 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 ) );

 void collect( void );

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

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

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

 using Pages = detail::PageHeap< CLASSES >;
 using Free = typename Pages::Free;
 using Page = typename Pages::Page;

 struct alignas( 64 ) Returns {
  std::atomic< Free * > top{ nullptr };
  };

 struct Heap;

 struct Batch {
  Heap * to = nullptr;
  Free * head = nullptr;
  Free * tail = nullptr;
  std::uint32_t n = 0;
  };

 static constexpr std::uint32_t BATCH = 32;

 struct Heap {
  std::thread::id id;
  Heap * link = nullptr;
  Pages pages{ this };
  Batch out[ CLASSES ];
  Returns returns[ CLASSES ];
  };

 static void send( Batch & b , std::size_t c );

 [[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 );
  }

 struct Cache {
  std::uint64_t id = 0;
  Heap * heap = nullptr;
  };

 [[nodiscard]] Heap * mine( void );

 Heap * find( void );

 [[nodiscard]] void * take( std::size_t c );

 void * refill( Heap & h , std::size_t c );

 void give( void * p , std::size_t c );

 inline static thread_local Cache s_cache;
 inline static std::atomic< std::uint64_t > s_ids{ 0 };

 const std::uint64_t f_id;
 std::atomic< Heap * > f_heaps{ nullptr };

 };  // end( class ConcurrentPoolResource )

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

}  // end( namespace ADS )

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

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

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

#endif  /* ConcurrentPool.h included */

/*--------------------------------------------------------------------------*/
/*----------------------- End File ConcurrentPool.h ------------------------*/
/*--------------------------------------------------------------------------*/