Removed code duplication by making generoc Pool also be static

This commit is contained in:
Istvan Haller
2021-08-23 19:54:26 +01:00
parent 35c9422913
commit c89a085c90
4 changed files with 33 additions and 97 deletions

View File

@@ -11,7 +11,7 @@ namespace snmalloc
static_assert(
SharedStateHandle::Options.CoreAllocIsPoolAllocated,
"Global statistics are available only for pool-allocated configurations");
auto* alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
auto* alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
auto alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::extract();
auto* first = Pool<CoreAllocator<SharedStateHandle>>::extract();
auto* alloc = first;
decltype(alloc) last;
@@ -74,10 +74,10 @@ namespace snmalloc
{
alloc->flush();
last = alloc;
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::extract(alloc);
alloc = Pool<CoreAllocator<SharedStateHandle>>::extract(alloc);
}
AllocPool<CoreAllocator<SharedStateHandle>>::restore(first, last);
Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
auto* alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
SharedStateHandle>();
while (alloc != nullptr)
{
alloc->debug_is_empty(nullptr);
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<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 = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
auto alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
SharedStateHandle>();
while (alloc != nullptr)
{
@@ -180,7 +180,7 @@ namespace snmalloc
}
count--;
}
alloc = AllocPool<CoreAllocator<SharedStateHandle>>::template iterate<
alloc = Pool<CoreAllocator<SharedStateHandle>>::template iterate<
SharedStateHandle>(alloc);
if (count != 0)

View File

@@ -380,7 +380,7 @@ namespace snmalloc
// Initialise the global allocator structures
ensure_init();
// Grab an allocator for this thread.
init(AllocPool<CoreAlloc>::template acquire<SharedStateHandle>(
init(Pool<CoreAlloc>::template acquire<SharedStateHandle>(
&(this->local_cache)));
}
@@ -403,7 +403,7 @@ namespace snmalloc
// Return underlying allocator to the system.
if constexpr (SharedStateHandle::Options.CoreAllocOwnsLocalState)
{
AllocPool<CoreAlloc>::template release<SharedStateHandle>(core_alloc);
Pool<CoreAlloc>::template release<SharedStateHandle>(core_alloc);
}
// Set up thread local allocator to look like

View File

@@ -21,10 +21,8 @@ namespace snmalloc
template<class T>
class PoolState
{
template<typename TT, typename SharedStateHandle>
friend class Pool;
template<typename TT>
friend class AllocPool;
friend class Pool;
private:
std::atomic_flag lock = ATOMIC_FLAG_INIT;
@@ -35,90 +33,30 @@ namespace snmalloc
constexpr PoolState() = default;
};
/**
* Class used to instantiate non-allocator pools using a Singleton PoolState.
*/
template<typename T, typename SharedStateHandle>
class Pool
class PoolStateHandle
{
PoolState<T> state;
static PoolState<T>& pool_state =
Singleton<PoolState<T>, PoolStateHandle::make_state>::get();
static PoolState<T>* make_state()
{
return ChunkAllocator::alloc_meta_data<PoolState<T>, SharedStateHandle>(
nullptr);
}
public:
static Pool* make() noexcept
static PoolState<T>& pool()
{
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;
return pool_state;
}
};
/**
* Collection of static wrappers for the allocator pool.
* The PoolState for this particular pool type is owned by the
* SharedStateHandle, so there is no object state in this class.
*/
template<typename T>
class AllocPool
class Pool
{
public:
template<typename SharedStateHandle, typename... Args>

View File

@@ -8,10 +8,8 @@ namespace snmalloc
class Pooled
{
private:
template<class TT, class SharedStateHandle>
friend class Pool;
template<class TT>
friend class AllocPool;
friend class Pool;
template<class a, Construction c>
friend class MPMCStack;