static_assert( __cplusplus > 2023'00 ); #include "ThreadSlab.h" #include namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m { namespace { namespace C { const std::size_t slabSize= 64 * 1024 * 1024; const bool debug= false; const bool debugLifecycle= false or C::debug; const bool debugAllocation= false or C::debug; const bool debugDeallocation= false or C::debug; } template< typename SP > void destroy( SP *p ) { p->~SP(); } namespace storage { thread_local Blob slab; } } [[nodiscard]] void * shim::allocate( std::size_t amt ) { // TODO: Alignment needs to be handled. const std::size_t req= amt + sizeof( Blob::StorageReservation ); // TODO: Larger allocations may be worth bespoke allocations, if they're rare one-off cases if( req > C::slabSize ) { auto exc= build_exception< AllocationError >( "Unable to allocate larger than the slab size." ); //exc.setAllocationAmount( req ); throw exc; } if( slab().size() < req ) slab().reset( std::max( req, C::slabSize ) ); if( C::debugAllocation ) { std::cerr << "Reporting " << slab().reservation().use_count() << " living allocations when " << (void *) &slab << " made an allocation." << std::endl; } auto next= slab().carveHead( req ); void *const rv= &next.as< Blob::StorageReservation >() + 1; // FIXME: The placement new here is potentially unaligned -- this may significantly impact // performance. It is also non-portable. new ( &next.template as< Blob::StorageReservation >() ) Blob::StorageReservation{ std::move( next.reservation() ) }; if( C::debugAllocation ) { std::cerr << "Reporting " << slab().reservation().use_count() << " living allocations when " << (void *) &slab() << " made an allocation." << std::endl; } return rv; } void shim::deallocate( void *p ) noexcept { if( C::debugDeallocation ) { std::cerr << "Reporting " << slab().reservation().use_count() << " living allocations when " << (void *) &slab() << " made a deallocation." << std::endl; } auto *const hidden= reinterpret_cast< Blob::StorageReservation * >( p ) - 1; destroy( hidden ); if( C::debugDeallocation ) { std::cerr << "Reporting " << slab().reservation().use_count() << " living allocations when " << (void *) &slab() << " made a deallocation." << std::endl; } } Blob & shim::slab() { return storage::slab; } }