diff --git a/Memory/ThreadSlab.h b/Memory/ThreadSlab.h index bc13568..9d99dc7 100644 --- a/Memory/ThreadSlab.h +++ b/Memory/ThreadSlab.h @@ -26,34 +26,15 @@ namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m template< typename T > class exports::ThreadSlab { - private: + public: inline static thread_local Blob slab; - using Slot= std::tuple< void *, Blob::StorageReservation >; - std::array< Slot, 16 > slots; - - void - dumpSlots() const - { - std::cerr << "Slot map for " << (void *) this << std::endl; - for( const auto &[ key, res ]: slots ) - { - std::cerr << (void *) key << " -> " << (void *) res.get() << std::endl; - } - } - - std::size_t - freeSlots() const - { - return std::count( begin( slots ), end( slots ), Slot{ nullptr, nullptr } ); - } - public: using value_type= T; using propagate_on_container_copy_assignment= std::true_type; using propagate_on_container_move_assignment= std::true_type; using propagate_on_container_swap= std::true_type; - using is_always_equal= std::false_type; + using is_always_equal= std::true_type; ThreadSlab select_on_container_copy_construction() { auto rv= ThreadSlab{}; } @@ -66,48 +47,53 @@ namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m ThreadSlab( ThreadSlab &&other ) : ThreadSlab( std::as_const( other ) ) {} + ~ThreadSlab() + { + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " is retired." << std::endl; + } + [[nodiscard]] T * allocate( const std::size_t amt ) { - std::cerr << "Pre allocation there are " << freeSlots() << " free slots" << std::endl; - dumpSlots(); - if( slab.size() < amt ) slab.reset( std::max( amt, C::slabSize ) ); + // TODO: Alignment? + const std::size_t req= amt + sizeof( Blob::StorageReservation ); + if( slab.size() < req ) slab.reset( std::max( req, C::slabSize ) ); - const auto slot= std::find( begin( slots ), end( slots ), Slot{ nullptr, nullptr } ); - assert( slot != end( slots ) ); + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made an allocation." << std::endl; - auto next= slab.carveHead( amt ); - const auto rv= &next.template as< T >(); - *slot= { rv, next.reservation() }; - std::cerr << "Allocated: " << (void *) rv << std::endl; + auto next= slab.carveHead( req ); + new ( &next.template as< Blob::StorageReservation >() ) Blob::StorageReservation{ next.reservation() }; + const auto rv= reinterpret_cast< T * >( &next.template as< Blob::StorageReservation >() + 1 ); + next.reset(); - std::cerr << "Post allocation there are " << freeSlots() << " free slots" << std::endl; - dumpSlots(); + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made an allocation." << std::endl; return rv; } + template< typename SP > + static void + destroy( SP *p ) + { + p->~SP(); + } + void deallocate( T *const p, const std::size_t /* ignored */ ) noexcept { - std::cerr << "Pre deallocation there are " << freeSlots() << " free slots" << std::endl; - dumpSlots(); - const auto slot= std::find_if( begin( slots ), end( slots ), - [p]( const auto &slot ){ const auto &[ which, _ ]= slot; return which == p; } ); - assert( slot != end( slots ) ); + 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 ); - *slot= { nullptr, nullptr }; - std::cerr << "Deallocated: " << (void *) p << std::endl; - - std::cerr << "Post deallocation there are " << freeSlots() << " free slots" << std::endl; - dumpSlots(); + std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when " + << (void *) this << " made a deallocation." << std::endl; } - friend constexpr bool - operator == ( const ThreadSlab &a, const ThreadSlab &b ) noexcept - { - return a.slots == b.slots; - } + friend constexpr bool operator == ( const ThreadSlab &, const ThreadSlab & ) noexcept { return true; } }; } diff --git a/Memory/ThreadSlab.test/0.cc b/Memory/ThreadSlab.test/0.cc index f29e03f..675b9f8 100644 --- a/Memory/ThreadSlab.test/0.cc +++ b/Memory/ThreadSlab.test/0.cc @@ -13,6 +13,13 @@ static auto init= Alepha::Utility::enroll <=[] using namespace Alepha::Memory::exports::ThreadSlab_m; using String= ThreadSlabString; + + "Check slab usage"_test <=[] + { + std::cout << "I see " << Alepha::Memory::ThreadSlab< char >::slab.reservation().use_count() << " reservations in a separate test." << +std::endl; + }; + "Can we work with simple `ThreadSlabStrings` without errors?"_test <=[] { String s; @@ -33,4 +40,10 @@ static auto init= Alepha::Utility::enroll <=[] std::cout << s3 << std::endl; }; + + "Check slab usage"_test <=[] + { + std::cout << "I see " << Alepha::Memory::ThreadSlab< char >::slab.reservation().use_count() << " reservations in a separate test." << +std::endl; + }; };