NFC: mpscq: prepare for pointer wrappers

This commit is contained in:
Nathaniel Filardo
2021-03-08 01:12:45 +00:00
committed by Matthew Parkinson
parent 93024a2471
commit 414be336f5

View File

@@ -6,16 +6,19 @@
#include <utility>
namespace snmalloc
{
template<class T>
template<
class T,
template<typename> typename Ptr = Pointer,
template<typename> typename AtomicPtr = AtomicPointer>
class MPSCQ
{
private:
static_assert(
std::is_same<decltype(T::next), std::atomic<T*>>::value,
"T->next must be a std::atomic<T*>");
std::is_same<decltype(T::next), AtomicPtr<T>>::value,
"T->next must be an AtomicPtr<T>");
std::atomic<T*> back{nullptr};
T* front = nullptr;
AtomicPtr<T> back{nullptr};
Ptr<T> front = nullptr;
public:
void invariant()
@@ -24,7 +27,7 @@ namespace snmalloc
SNMALLOC_ASSERT(front != nullptr);
}
void init(T* stub)
void init(Ptr<T> stub)
{
stub->next.store(nullptr, std::memory_order_relaxed);
front = stub;
@@ -32,9 +35,9 @@ namespace snmalloc
invariant();
}
T* destroy()
Ptr<T> destroy()
{
T* fnt = front;
Ptr<T> fnt = front;
back.store(nullptr, std::memory_order_relaxed);
front = nullptr;
return fnt;
@@ -42,34 +45,34 @@ namespace snmalloc
inline bool is_empty()
{
T* bk = back.load(std::memory_order_relaxed);
Ptr<T> bk = back.load(std::memory_order_relaxed);
return bk == front;
}
void enqueue(T* first, T* last)
void enqueue(Ptr<T> first, Ptr<T> last)
{
// Pushes a list of messages to the queue. Each message from first to
// last should be linked together through their next pointers.
invariant();
last->next.store(nullptr, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
T* prev = back.exchange(last, std::memory_order_relaxed);
Ptr<T> prev = back.exchange(last, std::memory_order_relaxed);
prev->next.store(first, std::memory_order_relaxed);
}
std::pair<T*, bool> dequeue()
std::pair<Ptr<T>, bool> dequeue()
{
// Returns the front message, or null if not possible to return a message.
invariant();
T* first = front;
T* next = first->next.load(std::memory_order_relaxed);
Ptr<T> first = front;
Ptr<T> next = first->next.load(std::memory_order_relaxed);
if (next != nullptr)
{
front = next;
Aal::prefetch(&(next->next));
SNMALLOC_ASSERT(front);
SNMALLOC_ASSERT(front != nullptr);
std::atomic_thread_fence(std::memory_order_acquire);
invariant();
return {first, true};