AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink > Class Template Reference

C++ implementation of Dmitry Vyukov's lock-free MPSC queue (Intrusive). More...

#include "MPSCQueue.h"

Public Member Functions

 MPSCQueueIntrusive ()
 Constructs a new MPSCQueueIntrusive object.
 
 ~MPSCQueueIntrusive ()
 Destroys the MPSCQueueIntrusive object.
 
void Enqueue (T *input)
 Enqueues a new item in the queue.
 
bool Dequeue (T *&result)
 Dequeues an item from the queue.
 

Private Member Functions

 MPSCQueueIntrusive (MPSCQueueIntrusive const &)=delete
 Deleted copy constructor.
 
MPSCQueueIntrusiveoperator= (MPSCQueueIntrusive const &)=delete
 Deleted copy assignment operator.
 

Private Attributes

std::aligned_storage_t< sizeof(T), alignof(T)> _dummy
 Storage for the dummy object.
 
T * _dummyPtr
 Pointer to the dummy object.
 
std::atomic< T * > _head
 Atomic pointer to the head node of the queue.
 
std::atomic< T * > _tail
 Atomic pointer to the tail node of the queue.
 

Detailed Description

template<typename T, std::atomic< T * > T::* IntrusiveLink>
class Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >

C++ implementation of Dmitry Vyukov's lock-free MPSC queue (Intrusive).

This queue allows multiple producers to enqueue items concurrently, but only one consumer can dequeue items. The queue is lock-free and intrusive, meaning that the enqueued objects must have an atomic link to the next item in the queue.

Template Parameters
TThe type of data that is being enqueued in the queue.
IntrusiveLinkA member pointer to the atomic link used for linking the nodes.

Constructor & Destructor Documentation

◆ MPSCQueueIntrusive() [1/2]

template<typename T , std::atomic< T * > T::* IntrusiveLink>
Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::MPSCQueueIntrusive ( )
inline

Constructs a new MPSCQueueIntrusive object.

Initializes the queue with a dummy node and sets up atomic pointers to the head and tail. The dummy node's atomic link is initialized.

153 : _dummyPtr(reinterpret_cast<T*>(std::addressof(_dummy))), _head(_dummyPtr), _tail(_dummyPtr)
154 {
155 // Initialize the intrusive link in the dummy node
156 std::atomic<T*>* dummyNext = new (&(_dummyPtr->*IntrusiveLink)) std::atomic<T*>();
157 dummyNext->store(nullptr, std::memory_order_release);
158 }
T * _dummyPtr
Pointer to the dummy object.
Definition MPSCQueue.h:233
std::atomic< T * > _head
Atomic pointer to the head node of the queue.
Definition MPSCQueue.h:234
std::atomic< T * > _tail
Atomic pointer to the tail node of the queue.
Definition MPSCQueue.h:235
std::aligned_storage_t< sizeof(T), alignof(T)> _dummy
Storage for the dummy object.
Definition MPSCQueue.h:232

References Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_dummyPtr.

◆ ~MPSCQueueIntrusive()

template<typename T , std::atomic< T * > T::* IntrusiveLink>
Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::~MPSCQueueIntrusive ( )
inline

Destroys the MPSCQueueIntrusive object.

Dequeues all items and deletes them.

166 {
167 T* output;
168 while (Dequeue(output))
169 delete output;
170 }
bool Dequeue(T *&result)
Dequeues an item from the queue.
Definition MPSCQueue.h:195

References Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::Dequeue().

◆ MPSCQueueIntrusive() [2/2]

template<typename T , std::atomic< T * > T::* IntrusiveLink>
Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::MPSCQueueIntrusive ( MPSCQueueIntrusive< T, IntrusiveLink > const &  )
privatedelete

Deleted copy constructor.

Member Function Documentation

◆ Dequeue()

template<typename T , std::atomic< T * > T::* IntrusiveLink>
bool Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::Dequeue ( T *&  result)
inline

Dequeues an item from the queue.

This function removes the item at the front of the queue and returns it.

Parameters
resultReference to a pointer where the dequeued item will be stored.
Returns
True if an item was successfully dequeued, false if the queue was empty.
196 {
197 T* tail = _tail.load(std::memory_order_acquire);
198 T* next = (tail->*IntrusiveLink).load(std::memory_order_acquire);
199 if (tail == _dummyPtr)
200 {
201 if (!next)
202 return false;
203
204 _tail.store(next, std::memory_order_release);
205 tail = next;
206 next = (next->*IntrusiveLink).load(std::memory_order_acquire);
207 }
208
209 if (next)
210 {
211 _tail.store(next, std::memory_order_release);
212 result = tail;
213 return true;
214 }
215
216 T* head = _head.load(std::memory_order_acquire);
217 if (tail != head)
218 return false;
219
221 next = (tail->*IntrusiveLink).load(std::memory_order_acquire);
222 if (next)
223 {
224 _tail.store(next, std::memory_order_release);
225 result = tail;
226 return true;
227 }
228 return false;
229 }
void Enqueue(T *input)
Enqueues a new item in the queue.
Definition MPSCQueue.h:179

References Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_dummyPtr, Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_head, Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_tail, and Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::Enqueue().

Referenced by Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::~MPSCQueueIntrusive().

◆ Enqueue()

template<typename T , std::atomic< T * > T::* IntrusiveLink>
void Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::Enqueue ( T *  input)
inline

Enqueues a new item in the queue.

This function adds a new item at the head of the queue.

Parameters
inputPointer to the item to be enqueued.

< Exchange with acquire-release semantics

180 {
181 // Set the next link to nullptr initially
182 (input->*IntrusiveLink).store(nullptr, std::memory_order_release);
183 T* prevHead = _head.exchange(input, std::memory_order_acq_rel);
184 (prevHead->*IntrusiveLink).store(input, std::memory_order_release);
185 }

References Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_head.

Referenced by Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::Dequeue().

◆ operator=()

template<typename T , std::atomic< T * > T::* IntrusiveLink>
MPSCQueueIntrusive & Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::operator= ( MPSCQueueIntrusive< T, IntrusiveLink > const &  )
privatedelete

Deleted copy assignment operator.

Member Data Documentation

◆ _dummy

template<typename T , std::atomic< T * > T::* IntrusiveLink>
std::aligned_storage_t<sizeof(T), alignof(T)> Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_dummy
private

Storage for the dummy object.

◆ _dummyPtr

template<typename T , std::atomic< T * > T::* IntrusiveLink>
T* Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_dummyPtr
private

◆ _head

template<typename T , std::atomic< T * > T::* IntrusiveLink>
std::atomic<T*> Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_head
private

◆ _tail

template<typename T , std::atomic< T * > T::* IntrusiveLink>
std::atomic<T*> Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::_tail
private

Atomic pointer to the tail node of the queue.

Referenced by Acore::Impl::MPSCQueueIntrusive< T, IntrusiveLink >::Dequeue().


The documentation for this class was generated from the following file: