00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef AMINO_STACK_H
00017 #define AMINO_STACK_H
00018
00019 #include <amino/smr.h>
00020 #include <stdexcept>
00021
00022 namespace amino {
00023
00024 using namespace internal;
00036
00037
00038
00039
00040
00041
00042 template<typename T> class LockFreeStack {
00043 public:
00047 class StackNode {
00048 public:
00049
00050 T data;
00051
00052 StackNode* next;
00053
00057 StackNode() {
00058 next = NULL;
00059 }
00060
00066 StackNode(const T& val) :
00067 data(val), next(NULL) {
00068 }
00069 };
00070
00071 private:
00072 #ifdef DEBUG_STACK
00073 atomic_int retries;
00074 atomic_int t_newNodes;
00075 #endif
00076
00077 atomic<StackNode *> top;
00078 SMR<StackNode, 1>* mm;
00079
00080
00081 LockFreeStack(const LockFreeStack& s) {
00082 }
00083
00084 LockFreeStack& operator=(const LockFreeStack& st) {
00085 }
00086
00087 public:
00091 LockFreeStack() {
00092 mm = getSMR<StackNode, 1> ();
00093 top.store(NULL, memory_order_relaxed);
00094
00095 #ifdef DEBUG_STACK
00096 retries = 0;
00097 #endif
00098 }
00099
00103 ~LockFreeStack() {
00104 StackNode *first = top.load(memory_order_relaxed);
00105 while (first != NULL) {
00106 StackNode *next = first->next;
00107 delete first;
00108 first = next;
00109 }
00110 }
00111
00119 bool pop(T& ret) {
00120 StackNode *oldTop, *newTop;
00121 typename SMR<StackNode, 1>::HP_Rec * hp = mm->getHPRec();
00122
00123 while (true) {
00124 oldTop = top.load(memory_order_relaxed);
00125 if (oldTop == NULL)
00126 return false;
00127
00128 mm->employ(hp, 0, oldTop);
00129
00130
00131 if (top.load(memory_order_relaxed) != oldTop)
00132 continue;
00133 newTop = oldTop->next;
00134 if (top.compare_swap(oldTop, newTop))
00135 break;
00136 #ifdef DEBUG_STACK
00137 retries++;
00138 #endif
00139 }
00140 mm->retire(hp, 0);
00141
00142 ret = oldTop->data;
00143 mm->delNode(hp, oldTop);
00144 return true;
00145 }
00146
00153 void push(const T d) {
00154 StackNode*oldTop, *newTop;
00155
00156 #ifdef DEBUG_STACK
00157 struct timeval start, end;
00158 gettimeofday(&start, NULL);
00159 #endif
00160
00161 #ifdef FREELIST
00162 newTop = mm->newNode();
00163 #else
00164 newTop = new StackNode();
00165 #endif
00166
00167 #ifdef DEBUG_STACK
00168 gettimeofday(&end, NULL);
00169 t_newNodes += 1000000*(end.tv_sec-start.tv_sec) + (end.tv_usec-start.tv_usec);
00170 #endif
00171
00172 newTop->data = d;
00173
00174
00175 do {
00176 oldTop = top.load(memory_order_relaxed);
00177 newTop->next = oldTop;
00178 } while (top.compare_swap(oldTop, newTop) == false);
00179 }
00180
00186 bool empty() {
00187 return top.load(memory_order_relaxed) == NULL;
00188 }
00189
00196 int size() {
00197 int ret = 0;
00198 StackNode *node = top.load(memory_order_relaxed);
00199 while (node != NULL) {
00200 ++ret;
00201 node = node -> next;
00202 }
00203 return ret;
00204 }
00205
00215 bool peekTop(T& ret) {
00216 StackNode *node = top.load(memory_order_relaxed);
00217 if (node == NULL)
00218 return false;
00219 ret = node->data;
00220 return true;
00221 }
00222 #ifdef DEBUG_STACK
00223 int getCASRetries() {
00224 return retries.load(memory_order_relaxed);
00225 }
00226 int getTimeNewNodes() {
00227 return t_newNodes.load(memory_order_relaxed);
00228 }
00229 #endif
00230
00231 };
00232
00233 }
00234 #endif
00235