From 414be336f53fd35ccd241da6c34c85fea5ab3c2f Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Mon, 8 Mar 2021 01:12:45 +0000 Subject: [PATCH] NFC: mpscq: prepare for pointer wrappers --- src/ds/mpscq.h | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/ds/mpscq.h b/src/ds/mpscq.h index 2b98dca..683d0db 100644 --- a/src/ds/mpscq.h +++ b/src/ds/mpscq.h @@ -6,16 +6,19 @@ #include namespace snmalloc { - template + template< + class T, + template typename Ptr = Pointer, + template typename AtomicPtr = AtomicPointer> class MPSCQ { private: static_assert( - std::is_same>::value, - "T->next must be a std::atomic"); + std::is_same>::value, + "T->next must be an AtomicPtr"); - std::atomic back{nullptr}; - T* front = nullptr; + AtomicPtr back{nullptr}; + Ptr front = nullptr; public: void invariant() @@ -24,7 +27,7 @@ namespace snmalloc SNMALLOC_ASSERT(front != nullptr); } - void init(T* stub) + void init(Ptr stub) { stub->next.store(nullptr, std::memory_order_relaxed); front = stub; @@ -32,9 +35,9 @@ namespace snmalloc invariant(); } - T* destroy() + Ptr destroy() { - T* fnt = front; + Ptr 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 bk = back.load(std::memory_order_relaxed); return bk == front; } - void enqueue(T* first, T* last) + void enqueue(Ptr first, Ptr 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 prev = back.exchange(last, std::memory_order_relaxed); prev->next.store(first, std::memory_order_relaxed); } - std::pair dequeue() + std::pair, 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 first = front; + Ptr 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};