Re-enabled generic Pool which uses ChunkAllocator. Allocator pool renamed to AllocPool.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include "allocconfig.h"
|
||||
#include "localcache.h"
|
||||
#include "metaslab.h"
|
||||
#include "pooled.h"
|
||||
#include "pool.h"
|
||||
#include "remotecache.h"
|
||||
#include "sizeclasstable.h"
|
||||
#include "slaballocator.h"
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace snmalloc
|
||||
static_assert(
|
||||
SharedStateHandle::Options.CoreAllocIsPoolAllocated,
|
||||
"Global statistics are available only for pool-allocated configurations");
|
||||
auto* alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
auto* alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>();
|
||||
|
||||
while (alloc != nullptr)
|
||||
@@ -20,7 +20,7 @@ namespace snmalloc
|
||||
if (a != nullptr)
|
||||
stats.add(*a);
|
||||
stats.add(alloc->stats());
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>(alloc);
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace snmalloc
|
||||
static_assert(
|
||||
SharedStateHandle::Options.CoreAllocIsPoolAllocated,
|
||||
"Global statistics are available only for pool-allocated configurations");
|
||||
auto alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
auto alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>();
|
||||
|
||||
while (alloc != nullptr)
|
||||
@@ -40,7 +40,7 @@ namespace snmalloc
|
||||
auto stats = alloc->stats();
|
||||
if (stats != nullptr)
|
||||
stats->template print<decltype(alloc)>(o, dumpid, alloc->id());
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>(alloc);
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace snmalloc
|
||||
// allocators that are not currently in use by any thread.
|
||||
// One atomic operation to extract the stack, another to restore it.
|
||||
// Handling the message queue for each stack is non-atomic.
|
||||
auto* first = Pool<CoreAllocator<SharedStateHandle>>::extract();
|
||||
auto* first = AllocPool<CoreAllocator<SharedStateHandle>>::extract();
|
||||
auto* alloc = first;
|
||||
decltype(alloc) last;
|
||||
|
||||
@@ -74,10 +74,10 @@ namespace snmalloc
|
||||
{
|
||||
alloc->flush();
|
||||
last = alloc;
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::extract(alloc);
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::extract(alloc);
|
||||
}
|
||||
|
||||
Pool<CoreAllocator<SharedStateHandle>>::restore(first, last);
|
||||
AllocPool<CoreAllocator<SharedStateHandle>>::restore(first, last);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace snmalloc
|
||||
"Global status is available only for pool-allocated configurations");
|
||||
// This is a debugging function. It checks that all memory from all
|
||||
// allocators has been freed.
|
||||
auto* alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
auto* alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>();
|
||||
|
||||
# ifdef SNMALLOC_TRACING
|
||||
@@ -111,7 +111,7 @@ namespace snmalloc
|
||||
std::cout << "debug_check_empty: Check all allocators!" << std::endl;
|
||||
# endif
|
||||
done = true;
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>();
|
||||
okay = true;
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace snmalloc
|
||||
# ifdef SNMALLOC_TRACING
|
||||
std::cout << "debug check empty: okay = " << okay << std::endl;
|
||||
# endif
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>(alloc);
|
||||
}
|
||||
}
|
||||
@@ -148,12 +148,12 @@ namespace snmalloc
|
||||
// Redo check so abort is on allocator with allocation left.
|
||||
if (!okay)
|
||||
{
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>();
|
||||
while (alloc != nullptr)
|
||||
{
|
||||
alloc->debug_is_empty(nullptr);
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>(alloc);
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,7 @@ namespace snmalloc
|
||||
static_assert(
|
||||
SharedStateHandle::Options.CoreAllocIsPoolAllocated,
|
||||
"Global status is available only for pool-allocated configurations");
|
||||
auto alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
auto alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>();
|
||||
while (alloc != nullptr)
|
||||
{
|
||||
@@ -180,7 +180,7 @@ namespace snmalloc
|
||||
}
|
||||
count--;
|
||||
}
|
||||
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
|
||||
SharedStateHandle>(alloc);
|
||||
|
||||
if (count != 0)
|
||||
|
||||
@@ -58,9 +58,12 @@ namespace snmalloc
|
||||
template<class SharedStateHandle>
|
||||
class LocalAllocator
|
||||
{
|
||||
using CoreAlloc = CoreAllocator<SharedStateHandle>;
|
||||
public:
|
||||
using StateHandle = SharedStateHandle;
|
||||
|
||||
private:
|
||||
using CoreAlloc = CoreAllocator<SharedStateHandle>;
|
||||
|
||||
// Free list per small size class. These are used for
|
||||
// allocation on the fast path. This part of the code is inspired by
|
||||
// mimalloc.
|
||||
@@ -375,7 +378,7 @@ namespace snmalloc
|
||||
// Initialise the global allocator structures
|
||||
ensure_init();
|
||||
// Grab an allocator for this thread.
|
||||
init(Pool<CoreAlloc>::template acquire<SharedStateHandle>(
|
||||
init(AllocPool<CoreAlloc>::template acquire<SharedStateHandle>(
|
||||
&(this->local_cache)));
|
||||
}
|
||||
|
||||
@@ -398,7 +401,7 @@ namespace snmalloc
|
||||
// Return underlying allocator to the system.
|
||||
if constexpr (SharedStateHandle::Options.CoreAllocOwnsLocalState)
|
||||
{
|
||||
Pool<CoreAlloc>::template release<SharedStateHandle>(core_alloc);
|
||||
AllocPool<CoreAlloc>::template release<SharedStateHandle>(core_alloc);
|
||||
}
|
||||
|
||||
// Set up thread local allocator to look like
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
#include "../ds/mpmcstack.h"
|
||||
#include "../pal/pal_concept.h"
|
||||
#include "pooled.h"
|
||||
#include "slaballocator.h"
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
/**
|
||||
* Pool of a particular type of object.
|
||||
* Pool of Allocators.
|
||||
*
|
||||
* This pool will never return objects to the OS. It maintains a list of all
|
||||
* objects ever allocated that can be iterated (not concurrency safe). Pooled
|
||||
@@ -20,8 +21,10 @@ namespace snmalloc
|
||||
template<class T>
|
||||
class PoolState
|
||||
{
|
||||
template<typename TT>
|
||||
template<typename TT, typename SharedStateHandle>
|
||||
friend class Pool;
|
||||
template<typename TT>
|
||||
friend class AllocPool;
|
||||
|
||||
private:
|
||||
std::atomic_flag lock = ATOMIC_FLAG_INIT;
|
||||
@@ -32,8 +35,85 @@ namespace snmalloc
|
||||
constexpr PoolState() = default;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename T, typename SharedStateHandle>
|
||||
class Pool
|
||||
{
|
||||
PoolState<T> state;
|
||||
|
||||
public:
|
||||
static Pool* make() noexcept
|
||||
{
|
||||
return ChunkAllocator::alloc_meta_data<Pool, SharedStateHandle>(nullptr);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
T* acquire(Args&&... args)
|
||||
{
|
||||
T* p = state.stack.pop();
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
p->set_in_use();
|
||||
return p;
|
||||
}
|
||||
|
||||
p = ChunkAllocator::alloc_meta_data<T, SharedStateHandle>(
|
||||
nullptr, std::forward<Args>(args)...);
|
||||
|
||||
FlagLock f(state.lock);
|
||||
p->list_next = state.list;
|
||||
state.list = p;
|
||||
|
||||
p->set_in_use();
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to the pool an object previously retrieved by `acquire`
|
||||
*
|
||||
* Do not return objects from `extract`.
|
||||
*/
|
||||
void release(T* p)
|
||||
{
|
||||
// The object's destructor is not run. If the object is "reallocated", it
|
||||
// is returned without the constructor being run, so the object is reused
|
||||
// without re-initialisation.
|
||||
p->reset_in_use();
|
||||
state.stack.push(p);
|
||||
}
|
||||
|
||||
T* extract(T* p = nullptr)
|
||||
{
|
||||
// Returns a linked list of all objects in the stack, emptying the stack.
|
||||
if (p == nullptr)
|
||||
return state.stack.pop_all();
|
||||
|
||||
return p->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to the pool a list of object previously retrieved by `extract`
|
||||
*
|
||||
* Do not return objects from `acquire`.
|
||||
*/
|
||||
void restore(T* first, T* last)
|
||||
{
|
||||
// Pushes a linked list of objects onto the stack. Use to put a linked
|
||||
// list returned by extract back onto the stack.
|
||||
state.stack.push(first, last);
|
||||
}
|
||||
|
||||
T* iterate(T* p = nullptr)
|
||||
{
|
||||
if (p == nullptr)
|
||||
return state.list;
|
||||
|
||||
return p->list_next;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class AllocPool
|
||||
{
|
||||
public:
|
||||
template<typename SharedStateHandle, typename... Args>
|
||||
|
||||
@@ -8,8 +8,10 @@ namespace snmalloc
|
||||
class Pooled
|
||||
{
|
||||
private:
|
||||
template<class TT>
|
||||
template<class TT, class SharedStateHandle>
|
||||
friend class Pool;
|
||||
template<class TT>
|
||||
friend class AllocPool;
|
||||
template<class a, Construction c>
|
||||
friend class MPMCStack;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user