forked from Alepha/Alepha
The slab pointer goes into a cookie.
This commit is contained in:
@ -26,34 +26,15 @@ namespace Alepha::Hydrogen::Memory ::detail:: ThreadSlab_m
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
class exports::ThreadSlab
|
class exports::ThreadSlab
|
||||||
{
|
{
|
||||||
private:
|
public:
|
||||||
inline static thread_local Blob slab;
|
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:
|
public:
|
||||||
using value_type= T;
|
using value_type= T;
|
||||||
using propagate_on_container_copy_assignment= std::true_type;
|
using propagate_on_container_copy_assignment= std::true_type;
|
||||||
using propagate_on_container_move_assignment= std::true_type;
|
using propagate_on_container_move_assignment= std::true_type;
|
||||||
using propagate_on_container_swap= 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{}; }
|
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( 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 *
|
[[nodiscard]] T *
|
||||||
allocate( const std::size_t amt )
|
allocate( const std::size_t amt )
|
||||||
{
|
{
|
||||||
std::cerr << "Pre allocation there are " << freeSlots() << " free slots" << std::endl;
|
// TODO: Alignment?
|
||||||
dumpSlots();
|
const std::size_t req= amt + sizeof( Blob::StorageReservation );
|
||||||
if( slab.size() < amt ) slab.reset( std::max( amt, C::slabSize ) );
|
if( slab.size() < req ) slab.reset( std::max( req, C::slabSize ) );
|
||||||
|
|
||||||
const auto slot= std::find( begin( slots ), end( slots ), Slot{ nullptr, nullptr } );
|
std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when "
|
||||||
assert( slot != end( slots ) );
|
<< (void *) this << " made an allocation." << std::endl;
|
||||||
|
|
||||||
auto next= slab.carveHead( amt );
|
auto next= slab.carveHead( req );
|
||||||
const auto rv= &next.template as< T >();
|
new ( &next.template as< Blob::StorageReservation >() ) Blob::StorageReservation{ next.reservation() };
|
||||||
*slot= { rv, next.reservation() };
|
const auto rv= reinterpret_cast< T * >( &next.template as< Blob::StorageReservation >() + 1 );
|
||||||
std::cerr << "Allocated: " << (void *) rv << std::endl;
|
next.reset();
|
||||||
|
|
||||||
std::cerr << "Post allocation there are " << freeSlots() << " free slots" << std::endl;
|
std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when "
|
||||||
dumpSlots();
|
<< (void *) this << " made an allocation." << std::endl;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename SP >
|
||||||
|
static void
|
||||||
|
destroy( SP *p )
|
||||||
|
{
|
||||||
|
p->~SP();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
deallocate( T *const p, const std::size_t /* ignored */ ) noexcept
|
deallocate( T *const p, const std::size_t /* ignored */ ) noexcept
|
||||||
{
|
{
|
||||||
std::cerr << "Pre deallocation there are " << freeSlots() << " free slots" << std::endl;
|
std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when "
|
||||||
dumpSlots();
|
<< (void *) this << " made a deallocation." << std::endl;
|
||||||
const auto slot= std::find_if( begin( slots ), end( slots ),
|
auto *const hidden= reinterpret_cast< Blob::StorageReservation * >( p ) - 1;
|
||||||
[p]( const auto &slot ){ const auto &[ which, _ ]= slot; return which == p; } );
|
destroy( hidden );
|
||||||
assert( slot != end( slots ) );
|
|
||||||
|
|
||||||
*slot= { nullptr, nullptr };
|
std::cerr << "Reporting " << slab.reservation().use_count() << " living allocations when "
|
||||||
std::cerr << "Deallocated: " << (void *) p << std::endl;
|
<< (void *) this << " made a deallocation." << std::endl;
|
||||||
|
|
||||||
std::cerr << "Post deallocation there are " << freeSlots() << " free slots" << std::endl;
|
|
||||||
dumpSlots();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool
|
friend constexpr bool operator == ( const ThreadSlab &, const ThreadSlab & ) noexcept { return true; }
|
||||||
operator == ( const ThreadSlab &a, const ThreadSlab &b ) noexcept
|
|
||||||
{
|
|
||||||
return a.slots == b.slots;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,13 @@ static auto init= Alepha::Utility::enroll <=[]
|
|||||||
using namespace Alepha::Memory::exports::ThreadSlab_m;
|
using namespace Alepha::Memory::exports::ThreadSlab_m;
|
||||||
using String= ThreadSlabString;
|
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 <=[]
|
"Can we work with simple `ThreadSlabStrings` without errors?"_test <=[]
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
@ -33,4 +40,10 @@ static auto init= Alepha::Utility::enroll <=[]
|
|||||||
|
|
||||||
std::cout << s3 << std::endl;
|
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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user