NFC: mpscq: prepare for pointer wrappers
This commit is contained in:
committed by
Matthew Parkinson
parent
93024a2471
commit
414be336f5
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user