TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
MPSCQueue.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef MPSCQueue_h__
19 #define MPSCQueue_h__
20 
21 #include <atomic>
22 #include <utility>
23 
24 // C++ implementation of Dmitry Vyukov's lock free MPSC queue
25 // http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue
26 template<typename T>
27 class MPSCQueue
28 {
29 public:
30  MPSCQueue() : _head(new Node()), _tail(_head.load(std::memory_order_relaxed))
31  {
32  Node* front = _head.load(std::memory_order_relaxed);
33  front->Next.store(nullptr, std::memory_order_relaxed);
34  }
35 
37  {
38  T* output;
39  while (this->Dequeue(output))
40  ;
41 
42  Node* front = _head.load(std::memory_order_relaxed);
43  delete front;
44  }
45 
46  void Enqueue(T* input)
47  {
48  Node* node = new Node(input);
49  Node* prevHead = _head.exchange(node, std::memory_order_acq_rel);
50  prevHead->Next.store(node, std::memory_order_release);
51  }
52 
53  bool Dequeue(T*& result)
54  {
55  Node* tail = _tail.load(std::memory_order_relaxed);
56  Node* next = tail->Next.load(std::memory_order_acquire);
57  if (!next)
58  return false;
59 
60  result = next->Data;
61  _tail.store(next, std::memory_order_release);
62  delete tail;
63  return true;
64  }
65 
66 private:
67  struct Node
68  {
69  Node() = default;
70  explicit Node(T* data) : Data(data) { Next.store(nullptr, std::memory_order_relaxed); }
71 
72  T* Data;
73  std::atomic<Node*> Next;
74  };
75 
76  std::atomic<Node*> _head;
77  std::atomic<Node*> _tail;
78 
79  MPSCQueue(MPSCQueue const&) = delete;
80  MPSCQueue& operator=(MPSCQueue const&) = delete;
81 };
82 
83 #endif // MPSCQueue_h__
MPSCQueue & operator=(MPSCQueue const &)=delete
bool Dequeue(T *&result)
Definition: MPSCQueue.h:53
MPSCQueue()
Definition: MPSCQueue.h:30
Definition: MPSCQueue.h:27
T * Data
Definition: MPSCQueue.h:72
Node()=default
int next(int i, int n)
Definition: RecastContour.cpp:469
STL namespace.
std::atomic< Node * > _tail
Definition: MPSCQueue.h:77
Definition: MPSCQueue.h:67
#define output
Definition: wire_format_lite.h:381
void Enqueue(T *input)
Definition: MPSCQueue.h:46
~MPSCQueue()
Definition: MPSCQueue.h:36
std::atomic< Node * > _head
Definition: MPSCQueue.h:76
Node(T *data)
Definition: MPSCQueue.h:70
#define input
Definition: wire_format_lite.h:242
std::atomic< Node * > Next
Definition: MPSCQueue.h:73
Data
Definition: molten_core.h:69