Program Listing for File Scratch.h
↰ Return to documentation for file (ADS/parallel/Scratch.h)
/*--------------------------------------------------------------------------*/
/*----------------------------- File Scratch.h -----------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/
#ifndef __ADS_Scratch
#define __ADS_Scratch
/* self-identification: #endif constant */
/*--------------------------------------------------------------------------*/
/*------------------------------ INCLUDES ----------------------------------*/
/*--------------------------------------------------------------------------*/
#include "ADS/memory/HugePageAllocator.h"
#include <algorithm>
#include <cstddef>
#include <mutex>
#include <utility>
/*--------------------------------------------------------------------------*/
/*--------------------------- NAMESPACE ------------------------------------*/
/*--------------------------------------------------------------------------*/
namespace ADS::detail {
class ScratchRoom {
public:
static std::byte * take( std::size_t b , std::size_t & got ) {
{
std::lock_guard< std::mutex > g( slot().lock );
if( slot().p && ( slot().size >= b ) ) {
got = slot().size;
return( std::exchange( slot().p , nullptr ) );
}
}
got = b;
return( HugePageAllocator< std::byte >().allocate( b ) );
}
static void give( std::byte * p , std::size_t b ) {
std::byte * drop = p;
std::size_t db = b;
{
std::lock_guard< std::mutex > g( slot().lock );
if( ! slot().p || ( slot().size < b ) ) {
std::swap( drop , slot().p );
std::swap( db , slot().size );
}
}
if( drop )
HugePageAllocator< std::byte >().deallocate( drop , db );
}
private:
struct Slot {
std::mutex lock;
std::byte * p = nullptr;
std::size_t size = 0;
~Slot() {
if( p ) HugePageAllocator< std::byte >().deallocate( p , size );
}
};
static Slot & slot( void ) {
static Slot s;
return( s );
}
};
template< class T >
class ScratchBuffer {
public:
explicit ScratchBuffer( std::size_t n )
: f_p( reinterpret_cast< T * >( ScratchRoom::take(
std::max< std::size_t >( n , 1 ) *
sizeof( T ) , f_b ) ) ) {}
~ScratchBuffer() {
ScratchRoom::give( reinterpret_cast< std::byte * >( f_p ) , f_b );
}
ScratchBuffer( const ScratchBuffer & ) = delete;
ScratchBuffer & operator=( const ScratchBuffer & ) = delete;
[[nodiscard]] T * data( void ) const { return( f_p ); }
private:
std::size_t f_b = 0;
T * f_p;
};
} // end( namespace ADS::detail )
/*--------------------------------------------------------------------------*/
#endif /* Scratch.h included */
/*--------------------------------------------------------------------------*/
/*--------------------------- End File Scratch.h ---------------------------*/
/*--------------------------------------------------------------------------*/