Add custom datastructure for local chunk cache

This commit adds a datastructure that provides efficient single-thread
stack behaviour, while allowing other threads to steal the whole
contents.
This commit is contained in:
Matthew Parkinson
2021-10-28 14:22:23 +01:00
committed by Matthew Parkinson
parent 72ccb23d02
commit 3407347925
2 changed files with 74 additions and 3 deletions

72
src/ds/spmcstack.h Normal file
View File

@@ -0,0 +1,72 @@
#pragma once
#include "aba.h"
#include "ptrwrap.h"
namespace snmalloc
{
/**
* Concurrent Stack
*
* This stack supports the following clients
* (push|pop)* || pop_all* || ... || pop_all*
*
* That is a single thread that can do push and pop, and other threads
* that do pop_all. pop_all if it returns a value, returns all of the
* stack, however, it may return nullptr if it races with either a push
* or a pop.
*
* The primary use case is single-threaded access, where other threads
* can attempt to steal all the values.
*/
template<class T>
class SPMCStack
{
private:
alignas(CACHELINE_SIZE) std::atomic<T*> stack{};
public:
constexpr SPMCStack() = default;
void push(T* item)
{
static_assert(
std::is_same<decltype(T::next), std::atomic<T*>>::value,
"T->next must be an std::atomic<T*>");
return push(item, item);
}
void push(T* first, T* last)
{
T* old_head = stack.exchange(nullptr, std::memory_order_relaxed);
last->next.store(old_head, std::memory_order_relaxed);
// Assume stays null as not allowed to race with pop or other pushes.
SNMALLOC_ASSERT(stack.load() == nullptr);
stack.store(first, std::memory_order_release);
}
T* pop()
{
if (stack.load(std::memory_order_relaxed) == nullptr)
return nullptr;
T* old_head = stack.exchange(nullptr);
if (unlikely(old_head == nullptr))
return nullptr;
auto next = old_head->next.load(std::memory_order_relaxed);
// Assume stays null as not allowed to race with pop or other pushes.
SNMALLOC_ASSERT(stack.load() == nullptr);
stack.store(next, std::memory_order_release);
return old_head;
}
T* pop_all()
{
return stack.exchange(nullptr);
}
};
} // namespace snmalloc

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../ds/mpmcstack.h"
#include "../ds/spmcstack.h"
#include "../mem/metaslab.h"
#include "../mem/sizeclasstable.h"
#include "../pal/pal_ds.h"
@@ -55,9 +56,7 @@ namespace snmalloc
/**
* Stack of slabs that have been returned for reuse.
*/
ModArray<
NUM_SLAB_SIZES,
ModArray<NUM_EPOCHS, MPMCStack<ChunkRecord, RequiresInit>>>
ModArray<NUM_SLAB_SIZES, ModArray<NUM_EPOCHS, SPMCStack<ChunkRecord>>>
chunk_stack;
/**