00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef AMINO_DEQUE_H
00024 #define AMINO_DEQUE_H
00025
00026 #include <stdexcept>
00027
00028 #include <amino/util.h>
00029 #include <amino/smr.h>
00030
00031 #ifdef DEBUG
00032 #include <amino/debug.h>
00033 #endif
00034
00035 namespace amino {
00036
00037 using namespace internal;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define STABLE 0
00059 #define RPUSH 1
00060 #define LPUSH 2
00061
00070 template<typename T>
00071 class LockFreeDeque {
00072 private:
00078 LockFreeDeque(const LockFreeDeque& dq) {
00079 }
00080
00081 LockFreeDeque& operator=(const LockFreeDeque& dq) {
00082 }
00083
00084 class Node {
00085 public:
00089 T data;
00090
00094 atomic<Node*> left;
00095
00099 atomic<Node*> right;
00100
00101 Node() :
00102 data() {
00103 left.store(NULL, memory_order_relaxed);
00104 right.store(NULL, memory_order_relaxed);
00105 }
00106
00107 Node(const T& val) :
00108 data(val) {
00109 left.store(NULL, memory_order_relaxed);
00110 right.store(NULL, memory_order_relaxed);
00111 }
00112 };
00113
00120 typedef union AnchorType {
00124 struct {
00125 volatile unsigned long low;
00126 volatile unsigned long high;
00127 }all;
00128
00132 struct {
00133
00134 volatile unsigned long left;
00135
00136
00137
00138
00139 volatile unsigned long right :(sizeof(unsigned long) * 8 - 2);
00140
00141
00142
00143
00144 volatile unsigned long status :2;
00145 }fields;
00146
00147 public:
00153 void setRight(Node * pNode) {
00154 fields.right = ((unsigned long) pNode) >> 2;
00155 assert(getRight() == pNode);
00156 }
00157
00158 Node * getRight() {
00159 return (Node *) (fields.right << 2);
00160 }
00161
00162 Node * getLeft() {
00163 return (Node *) fields.left;
00164 }
00165 #if defined(BIT32)
00166 }__attribute__((aligned(8))) Anchor_t;
00167 #elif defined(BIT64)
00168 }__attribute__((aligned(16))) Anchor_t;
00169 #endif
00170
00171 SMR<Node, 3>* mm;
00172 typedef typename SMR<Node, 3>::HP_Rec HazardP;
00173 volatile Anchor_t anchor;
00174
00182 void copyAnchor(Anchor_t& newAnchor) __attribute__((noinline)) {
00183 do {
00184 newAnchor.all.low = anchor.all.low;
00185 newAnchor.all.high = anchor.all.high;
00186 }while (newAnchor.all.low != anchor.all.low || newAnchor.all.high
00187 != anchor.all.high);
00188 }
00189 public:
00193 LockFreeDeque() {
00194
00195 mm = getSMR<Node, 3> ();
00196
00197 anchor.all.high = 0;
00198 anchor.all.low = 0;
00199 }
00200
00206 void enqueue(const T &d) {
00207 pushRight(d);
00208 }
00209
00215 bool dequeue(T& ret) {
00216 return popLeft(ret);
00217 }
00218
00222 virtual ~LockFreeDeque() {
00223 Anchor_t local_anchor;
00224 local_anchor.all.low = anchor.all.low;
00225 local_anchor.all.high = anchor.all.high;
00226
00227 Node * left = local_anchor.getLeft();
00228 Node * right = local_anchor.getRight();
00229 if(left!=NULL) {
00230 Node * current = left;
00231 while(current!=right) {
00232 Node * next = current->right.load(memory_order_relaxed);
00233 delete current;
00234 current = next;
00235 }
00236 delete right;
00237 }
00238 }
00239
00246 virtual void pushRight(const T& data) __attribute__((noinline)) {
00247 Anchor_t old_anchor, new_anchor;
00248 HazardP * hp = mm->getHPRec();
00249
00250 #ifdef FREELIST
00251 Node* node = mm->newNode(hp);
00252 node->data = data;
00253 #else
00254
00255 Node* node = new Node(data);
00256 #endif
00257
00258
00259 assert(((unsigned long) node) % 4 == 0);
00260
00261
00262 while (true) {
00263
00264 copyAnchor(old_anchor);
00265
00266 if (old_anchor.fields.right == 0) {
00267 assert(old_anchor.fields.left == 0);
00268
00269 new_anchor.fields.left = (unsigned long) node;
00270 new_anchor.setRight(node);
00271 new_anchor.fields.status = old_anchor.fields.status;
00272
00273
00274
00275
00276
00277
00278 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00279 return;
00280 }
00281 }
00282
00283 else if (old_anchor.fields.status == STABLE) {
00284 node->left.store(old_anchor.getRight());
00285 assert(node->left.load() != NULL);
00286
00287
00288 new_anchor.fields.left = old_anchor.fields.left;
00289 new_anchor.setRight(node);
00290 new_anchor.fields.status = RPUSH;
00291
00292
00293
00294
00295
00296
00297
00298 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00299 stabilizeRight(new_anchor);
00300 return;
00301 }
00302 }
00303
00304 else {
00305 stabilize(old_anchor);
00306 }
00307 }
00308 }
00309
00316 virtual void pushLeft(const T& data) __attribute__((noinline)) {
00317 Anchor_t old_anchor, new_anchor;
00318 HazardP * hp = mm->getHPRec();
00319
00320 #ifdef FREELIST
00321 Node* node = mm->newNode(hp);
00322 node->data = data;
00323 #else
00324
00325 Node* node = new Node(data);
00326 #endif
00327
00328
00329 assert(((unsigned long) node) % 4 == 0);
00330
00331
00332 while (true) {
00333
00334 copyAnchor(old_anchor);
00335
00336 if (old_anchor.fields.left == 0) {
00337 assert(old_anchor.fields.right == 0);
00338
00339 new_anchor.fields.left = (unsigned long) node;
00340 new_anchor.setRight(node);
00341 new_anchor.fields.status = old_anchor.fields.status;
00342
00343
00344
00345
00346
00347
00348 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00349 break;
00350 }
00351 }
00352
00353 else if (old_anchor.fields.status == STABLE) {
00354 node->right.store((Node*) old_anchor.fields.left, memory_order_relaxed);
00355 assert(node->right.load() != NULL);
00356
00357 new_anchor.fields.right = old_anchor.fields.right;
00358 new_anchor.fields.left = (unsigned long) node;
00359 new_anchor.fields.status = LPUSH;
00360
00361
00362
00363
00364
00365
00366
00367 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00368 stabilizeLeft(new_anchor);
00369 break;
00370 }
00371 }
00372
00373 else {
00374 stabilize(old_anchor);
00375 }
00376 }
00377 }
00378
00388 virtual bool popRight(T& ret) __attribute__((noinline)) {
00389 Anchor_t old_anchor, new_anchor;
00390 Node* prev;
00391
00392 HazardP * hp = mm->getHPRec();
00393
00394 while (true) {
00395 copyAnchor(old_anchor);
00396
00397 if (old_anchor.fields.right == 0) {
00398 assert(old_anchor.fields.left == 0);
00399 return false;
00400 }
00401
00402 if (old_anchor.getRight() == old_anchor.getLeft()) {
00403
00404 new_anchor.fields.status = old_anchor.fields.status;
00405 new_anchor.fields.left = 0;
00406 new_anchor.fields.right = 0;
00407
00408 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00409 break;
00410 }
00411 }
00412
00413 else if (old_anchor.fields.status == STABLE) {
00418 Node * right = old_anchor.getRight();
00419
00420 mm->employ(hp, 0, (Node*) old_anchor.fields.left);
00421 mm->employ(hp, 1, right);
00422
00423 assert(right != NULL);
00424 if (anchor.all.high != old_anchor.all.high || anchor.all.low
00425 != old_anchor.all.low) {
00426 continue;
00427 }
00428 prev = right->left.load();
00429 #ifdef DEBUG
00430 if(prev==NULL) {
00431 dumpDeque(old_anchor);
00432 assert(prev!=NULL);
00433 }
00434 #endif
00435
00436
00437 new_anchor.fields.left = old_anchor.fields.left;
00438 new_anchor.setRight(prev);
00439 new_anchor.fields.status = old_anchor.fields.status;
00440
00441
00442
00443 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00444 break;
00445 }
00446 }
00447
00448 else {
00449 stabilize(old_anchor);
00450 }
00451 }
00452 Node * right = old_anchor.getRight();
00453 ret = right->data;
00454 mm->delNode(hp, right);
00455 return true;
00456 }
00457
00458 #ifdef DEBUG
00459 void dumpDeque(Anchor_t an) {
00460
00461 char buffer[4096];
00462 int pos = sprintf(buffer, "Local Anchor: left: %lx right: %lx status: %lx\n",
00463 an.fields.left, an.fields.right, an.fields.status);
00464 pos = sprintf(buffer+pos, "Shared Anchor: left: %lx right: %lx status: %lx\n",
00465 an.fields.left, an.fields.right, an.fields.status);
00466 cout <<buffer;
00467 pos =0;
00468 if(an.fields.left!=0) {
00469 pos += sprintf(buffer+pos, "From Left:\n");
00470 Node * left = (Node *) an.fields.left;
00471 Node * right = an.getRight();
00472
00473 Node * current = left;
00474 int i =0;
00475 while(current != right) {
00476 pos += sprintf(buffer+pos,
00477 "Index: %d node %p left %p right %p\n",
00478 i, current, current->left.load(), current->right.load());
00479 i++;
00480 current = current->right.load();
00481 }
00482 }
00483 cout << buffer;
00484 }
00485 #endif
00486
00497 virtual bool popLeft(T& ret) __attribute__((noinline)) {
00498 Anchor_t old_anchor, new_anchor;
00499 Node* prev;
00500 HazardP * hp = mm->getHPRec();
00501
00502 while (true) {
00503 copyAnchor(old_anchor);
00504 if (old_anchor.fields.right == 0) {
00505 assert(old_anchor.fields.left == 0);
00506 return false;
00507 }
00508
00509 if (old_anchor.getRight() == old_anchor.getLeft()) {
00510 new_anchor.fields.status = old_anchor.fields.status;
00511 new_anchor.fields.left = 0;
00512 new_anchor.fields.right = 0;
00513 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true)
00514 break;
00515 } else if (old_anchor.fields.status == STABLE) {
00521 mm->employ(hp, 0, (Node*) old_anchor.fields.left);
00522 mm->employ(hp, 1, old_anchor.getRight());
00523
00524
00525 Node * left = (Node *) old_anchor.fields.left;
00526 assert(left != NULL);
00527
00528
00529 if (anchor.all.high != old_anchor.all.high || anchor.all.low
00530 != old_anchor.all.low) {
00531 continue;
00532 }
00533 prev = left->right.load();
00534 #ifdef DEBUG
00535 if(prev==NULL) {
00536 dumpDeque(old_anchor);
00537 assert(prev!=NULL);
00538 }
00539 #endif
00540
00541 new_anchor.fields.left = (unsigned long) prev;
00542 new_anchor.fields.right = old_anchor.fields.right;
00543 new_anchor.fields.status = old_anchor.fields.status;
00544 if (casd(&anchor.all, &old_anchor.all, &new_anchor.all) == true) {
00545 break;
00546 }
00547 } else {
00548 stabilize(old_anchor);
00549 }
00550 }
00551 Node * left = (Node *) old_anchor.fields.left;
00552 ret = left->data;
00553 mm->delNode(hp, left);
00554 return true;
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564 int size() {
00565 Anchor_t old_anchor;
00566 copyAnchor(old_anchor);
00567 if (old_anchor.fields.left == 0) {
00568 return 0;
00569 } else if (old_anchor.getLeft() == old_anchor.getRight()) {
00570 return 1;
00571 } else {
00572 int _size = 2;
00573 Node * left = (Node *) old_anchor.fields.left;
00574 Node * right = old_anchor.getRight();
00575 while (true) {
00576 Node * lNext = left->right.load(memory_order_relaxed);
00577 if (lNext == right) {
00578 break;
00579 }
00580 _size++;
00581 left = lNext;
00582 }
00583 return _size;
00584 }
00585 }
00586
00592 bool empty() const {
00593 if (anchor.fields.left == 0) {
00594 return true;
00595 } else {
00596 return false;
00597 }
00598 }
00599
00608 bool peekRight(T& ret) {
00609 Node* right = (Node *) (anchor.fields.right << 2);
00610 if (right != NULL) {
00611 ret = right -> data;
00612 return true;
00613 } else
00614 return false;
00615 }
00616
00625 bool peekLeft(T& ret) {
00626 Node* left = (Node *) (anchor.fields.left);
00627 if (left != NULL) {
00628 ret = left -> data;
00629 return true;
00630 } else
00631 return false;
00632 }
00633 private:
00639 void stabilize(Anchor_t a) {
00640 if (a.fields.status == RPUSH) {
00641 stabilizeRight(a);
00642 } else {
00643 stabilizeLeft(a);
00644 }
00645 }
00646
00653 void stabilizeRight(Anchor_t a) {
00654 Node *prev, *prevnext;
00655 Anchor_t new_anchor;
00656 Node* al = (Node*) a.fields.left;
00657 Node* ar = a.getRight();
00658 HazardP * hp = mm->getHPRec();
00659
00660
00661
00662
00663 mm->employ(hp, 0, al);
00664 mm->employ(hp, 1, ar);
00665
00666 #ifdef DEBUG
00667 if(ar==NULL||ar==NULL) {
00668
00669 dumpDeque(a);
00670 assert(false);
00671 }
00672 #endif
00673 if (anchor.all.high != a.all.high || anchor.all.low != a.all.low) {
00674 return;
00675 }
00676 prev = ar->left.load();
00677 #ifdef DEBUG
00678 if(prev==NULL) {
00679
00680 dumpDeque(a);
00681 assert(prev!=NULL);
00682 }
00683 #endif
00684
00685
00686
00687
00688 mm->employ(hp, 2, prev);
00689
00690 if (anchor.all.high != a.all.high || anchor.all.low != a.all.low) {
00691 return;
00692 }
00693 prevnext = prev->right.load();
00694
00695 if (prevnext != ar) {
00696 if (anchor.all.high != a.all.high || anchor.all.low != a.all.low) {
00697 return;
00698 }
00699 if (prev->right.compare_swap(prevnext, ar) != true) {
00700 return;
00701 }
00702 }
00703 new_anchor.all.high = a.all.high;
00704 new_anchor.all.low = a.all.low;
00705 new_anchor.fields.status = STABLE;
00706
00707 casd(&anchor.all, &a.all, &new_anchor.all);
00708 }
00709
00715 void stabilizeLeft(Anchor_t a) {
00716 Node *prev, *prevnext;
00717 Anchor_t new_anchor;
00718 Node* al = (Node*) a.fields.left;
00719 Node* ar = a.getRight();
00720
00721 HazardP * hp = mm->getHPRec();
00722
00723
00724
00725 mm->employ(hp, 0, al);
00726 mm->employ(hp, 1, ar);
00727 #ifdef DEBUG
00728 if(ar==NULL||ar==NULL) {
00729
00730 dumpDeque(a);
00731 assert(false);
00732 }
00733 #endif
00734
00735 if (anchor.all.high != a.all.high || anchor.all.low != a.all.low) {
00736 return;
00737 }
00738 prev = al->right.load();
00739 #ifdef DEBUG
00740 if(prev==NULL) {
00741
00742 dumpDeque(a);
00743 assert(prev!=NULL);
00744 }
00745 #endif
00746
00747
00748
00749 mm->employ(hp, 2, prev);
00750
00751 prevnext = prev->left.load();
00752 if (anchor.all.high != a.all.high || anchor.all.low != a.all.low) {
00753 return;
00754 }
00755 if (prevnext != al) {
00756 if (anchor.all.high != a.all.high || anchor.all.low != a.all.low) {
00757 return;
00758 }
00759 if (prev->left.compare_swap(prevnext, al) != true) {
00760 return;
00761 }
00762 }
00763 new_anchor.all.high = a.all.high;
00764 new_anchor.all.low = a.all.low;
00765 new_anchor.fields.status = STABLE;
00766 casd(&anchor.all, &a.all, &new_anchor.all);
00767 }
00768
00769 };
00770 }
00771
00772 #endif