diff --git a/Memory/Blob.h b/Memory/Blob.h index 58ebab8..b1ee065 100644 --- a/Memory/Blob.h +++ b/Memory/Blob.h @@ -227,11 +227,8 @@ namespace Alepha::Hydrogen ::detail:: Blob_m * possible extra space, due to alignment). */ Blob - carveHead( const std::size_t unalignedAmount, Alignment alignment= Alignment{ 1 } ) + carveHead( const std::size_t amount ) { - assert( std::popcount( alignment.amt ) == 1 ); - // TODO: Consider arithmetic overflow, here. - const std::size_t amount= alignTo( ( reinterpret_cast< std::uintptr_t >( data() ) % alignment.amt ) + unalignedAmount, alignment ); if( amount > size() ) throw DataCarveTooLargeError( data(), amount, size() ); if( not storage ) { diff --git a/Memory/CMakeLists.txt b/Memory/CMakeLists.txt index 694f4ac..cb3030b 100644 --- a/Memory/CMakeLists.txt +++ b/Memory/CMakeLists.txt @@ -1,3 +1,2 @@ add_subdirectory( Blob.test ) add_subdirectory( ThreadSlab.test ) -add_subdirectory( Blob.test ) diff --git a/Memory/ThreadSlab.h b/Memory/ThreadSlab.h index e3bd28d..7e5a4c7 100644 --- a/Memory/ThreadSlab.h +++ b/Memory/ThreadSlab.h @@ -21,6 +21,11 @@ namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m 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 debugDeallocations= false or C::debug; } template< typename T > @@ -49,27 +54,41 @@ namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m ~ThreadSlab() { - std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " - << (void *) this << " is retired." << std::endl; + if( C::debugLifecycle ) + { + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " is retired." << std::endl; + } } [[nodiscard]] T * allocate( const std::size_t amt ) { - // TODO: Alignment? + // 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 ) throw std::bad_alloc{}; //{ "Unable to allocate larger than the slab size." }; if( slab.size() < req ) slab.reset( std::max( req, C::slabSize ) ); - std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " - << (void *) this << " made an allocation." << std::endl; + if( C::debugAllocation ) + { + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made an allocation." << std::endl; + } - auto next= slab.carveHead( req, Alignment{ sizeof( Blob::StorageReservation ) } ); + auto next= slab.carveHead( req + sizeof( Blob::StorageReservation ) ); const auto rv= reinterpret_cast< T * >( &next.template as< Blob::StorageReservation >() + 1 ); + + // FIXME: The placement new here is potentially unaligned -- this may significantly impact + // performance. new ( &next.template as< Blob::StorageReservation >() ) Blob::StorageReservation{ std::move( next.reservation() ) }; - std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " - << (void *) this << " made an allocation." << std::endl; + if( C::debugAllocation ) + { + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made an allocation." << std::endl; + } return rv; } @@ -84,13 +103,20 @@ namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m void deallocate( T *const p, const std::size_t /* ignored */ ) noexcept { - std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " - << (void *) this << " made a deallocation." << std::endl; + if( C::debugDeallocation ) + { + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made a deallocation." << std::endl; + } + auto *const hidden= reinterpret_cast< Blob::StorageReservation * >( p ) - 1; destroy( hidden ); - std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " - << (void *) this << " made a deallocation." << std::endl; + if( C::debugDeallocation ) + { + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made a deallocation." << std::endl; + } } friend constexpr bool operator == ( const ThreadSlab &, const ThreadSlab & ) noexcept { return true; }