00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef AMINO_QUEUE_H
00018 #define AMINO_QUEUE_H
00019
00020 #include "smr.h"
00021 #include <stdexcept>
00022
00023 namespace amino {
00024
00025
00026 using namespace internal;
00056 template<typename T> class LockFreeQueue {
00057 private:
00062 static const bool hasBackoff = false;
00063
00064
00065
00066
00067 class Node {
00068 public:
00069 T data;
00070 atomic<Node*> next;
00071 Node() {
00072 next.store(NULL, memory_order_relaxed);
00073 }
00074
00075 Node(const T& val) :
00076 data(val) {
00077 next.store(NULL, memory_order_relaxed);
00078 }
00079 };
00080
00084 atomic<Node *> head;
00085
00089 atomic<Node *> tail;
00090
00091
00092 SMR<Node, 2>* mm;
00093
00094
00095 LockFreeQueue(const LockFreeQueue& q) {
00096 }
00097
00098 LockFreeQueue& operator=(const LockFreeQueue& q) {
00099 }
00100
00101 public:
00105 LockFreeQueue() {
00106
00107 mm = getSMR<Node, 2> ();
00108
00109
00110 Node* dummy = new Node();
00111 head.store(dummy, memory_order_relaxed);
00112 tail.store(dummy, memory_order_relaxed);
00113 }
00114
00118 ~LockFreeQueue() {
00119 Node* first = head.load(memory_order_relaxed)->next.load(
00120 memory_order_relaxed);
00121 while (NULL != first) {
00122 if (first == tail.load(memory_order_relaxed)) {
00123 delete first;
00124 break;
00125 }
00126 Node* next = first->next.load(memory_order_relaxed);
00127 delete first;
00128 first = next;
00129 }
00130
00131 delete head.load(memory_order_relaxed);
00132 }
00133
00139 void enqueue(T d) {
00140 Node *pTail;
00141 Node *pTailNext;
00142
00143 int waitForBackoff = 10000;
00144 #ifdef FREELIST
00145 Node * node = mm->newNode();
00146 node->data = d;
00147 #else
00148 Node * node = new Node(d);
00149 #endif
00150
00151 while (true) {
00152
00153
00154
00155 Node* temp = NULL;
00156 pTail = tail.load(memory_order_relaxed);
00157
00158 mm->employ(0, pTail);
00159
00160
00161 if (tail.load(memory_order_seq_cst) != pTail)
00162 continue;
00163 pTailNext = pTail->next.load(memory_order_acquire);
00164
00165
00166
00167 if (tail.load(memory_order_relaxed) != pTail)
00168 continue;
00169
00170
00171 if (pTailNext != NULL) {
00172
00173 tail.compare_swap(pTail, pTailNext);
00174 continue;
00175 }
00176
00177
00178 if (pTail->next.compare_swap(temp, node))
00179 break;
00180
00181 if (hasBackoff) {
00182 usleep(waitForBackoff);
00183 waitForBackoff <<= 1;
00184 }
00185 }
00186
00187 tail.compare_swap(pTail, node);
00188 }
00189
00194 bool dequeue(T& ret) {
00195 Node *pHead;
00196 Node *pTail;
00197 Node *pHeadNext;
00198
00199 int waitForBackoff = 10000;
00200 while (true) {
00201 pHead = head.load(memory_order_relaxed);
00202
00203 mm->employ(0, pHead);
00204
00205 if (head.load(memory_order_seq_cst) != pHead)
00206 continue;
00207
00208 pTail = tail.load(memory_order_relaxed);
00209 pHeadNext = pHead->next.load(memory_order_relaxed);
00210
00211 mm->employ(1, pHeadNext);
00212
00213
00214 if (head.load(memory_order_seq_cst) != pHead)
00215 continue;
00216 if (pHeadNext == NULL)
00217 return false;
00218 if (pHead == pTail) {
00219 tail.compare_swap(pTail, pHeadNext);
00220 continue;
00221 }
00222 ret = pHeadNext->data;
00223
00224
00225
00226 if (head.compare_swap(pHead, pHeadNext))
00227 break;
00228
00229 if (hasBackoff) {
00230 usleep(waitForBackoff);
00231 waitForBackoff <<= 1;
00232 }
00233 }
00234 mm->delNode(pHead);
00235 return true;
00236 }
00237
00242 bool empty() {
00243 return NULL == head.load(memory_order_relaxed)->next.load(
00244 memory_order_relaxed);
00245 }
00246
00252 int size() {
00253 int result = 0;
00254 Node *front = head.load(memory_order_relaxed)->next.load(memory_order_relaxed);
00255 while (front != NULL) {
00256 ++result;
00257 if (front == tail.load(memory_order_relaxed))
00258 break;
00259 front = front->next.load(memory_order_relaxed);
00260 }
00261 return result;
00262 }
00263
00273 bool peekFront(T& top) {
00274 Node *front = (head.load(memory_order_relaxed)->next).load(memory_order_relaxed);
00275 if (front == NULL) {
00276 return false;
00277 }
00278 top = front->data;
00279 return true;
00280 }
00281 };
00282 }
00283
00284 #endif