bool NBBST<T, Threads>::HelpDelete(Info* op){ infos.publish(op->p->update, 0); infos.publish(op->pupdate, 1); infos.publish(op, 2); Update result = op->p->update; //If we succeed if(CASPTR(&op->p->update, op->pupdate, Mark(op, MARK))){ if(op->pupdate){ infos.releaseNode(Unmark(op->pupdate)); } nodes.releaseNode(op->l); HelpMarked(Unmark(op)); infos.releaseAll(); return true; } //if another has succeeded for us else if(getState(op->p->update) == MARK && Unmark(op->p->update) == Unmark(op)){ HelpMarked(Unmark(op)); infos.releaseAll(); return true; } else { Help(result); infos.publish(op->gp->update, 0); infos.publish(op, 1); CASPTR(&op->gp->update, Mark(op, DFLAG), Mark(op, CLEAN)); infos.releaseAll(); return false; } }
inline static void connectQueue(void) { EnqState lsp_data; pointer_t tmp_sp; LoadFence(); tmp_sp = enq_sp; lsp_data = enq_pool[tmp_sp.struct_data.index]; CASPTR(&lsp_data.link_a->next, null, lsp_data.link_b); }
void NBBST<T, Threads>::HelpInsert(Info* op){ infos.publish(op, 0); infos.publish(op->p->update, 1); CASChild(op->p, op->l, op->newInternal); CASPTR(&op->p->update, Mark(op, IFLAG), Mark(op, CLEAN)); infos.releaseAll(); }
inline RetVal LFStackPop(LFStack *l, LFStackThreadState *th_state) { reset_backoff(&th_state->backoff); do { Node *old_top = (Node *) l->top; if (old_top == null) return (RetVal)INT_MIN; if(CASPTR(&l->top, old_top, old_top->next)) return old_top->val; else backoff_delay(&th_state->backoff); } while (true) ; }
void NBBST<T, Threads>::CASChild(Node* parent, Node* old, Node* newNode){ nodes.publish(old, 0); nodes.publish(newNode, 1); if(newNode->key < parent->key){ nodes.publish(parent->left, 2); if(CASPTR(&parent->left, old, newNode)){ if(old){ nodes.releaseNode(old); } } } else { nodes.publish(parent->right, 2); if(CASPTR(&parent->right, old, newNode)){ if(old){ nodes.releaseNode(old); } } } nodes.releaseAll(); }
inline void LFStackPush(LFStack *l, LFStackThreadState *th_state, ArgVal arg) { Node *n; n = alloc_obj(&th_state->pool); reset_backoff(&th_state->backoff); n->val = arg; do { Node *old_top = (Node *) l->top; // top is volatile n->next = old_top; if (CASPTR(&l->top, old_top, n) == true) break; else backoff_delay(&th_state->backoff); } while(true); }
bool NBBST<T, Threads>::remove(T value){ int key = hash(value); SearchResult search; while(true){ Search(key, &search); nodes.publish(search.l, 0); if(search.l->key != key){ return false; } if(getState(search.gpupdate) != CLEAN){ Help(search.gpupdate); } else if(getState(search.pupdate) != CLEAN){ Help(search.pupdate); } else { infos.publish(search.gp->update, 0); infos.publish(search.gpupdate, 1); Info* op = newDInfo(search.gp, search.p, search.l, search.pupdate); infos.publish(op, 2); Update result = search.gp->update; if(CASPTR(&search.gp->update, search.gpupdate, Mark(op, DFLAG))){ if(search.gpupdate){ infos.releaseNode(Unmark(search.gpupdate)); } infos.releaseAll(); if(HelpDelete(op)){ nodes.releaseAll(); return true; } } else { infos.releaseNode(op); infos.releaseAll(); Help(result); } } nodes.releaseAll(); } }
void NBBST<T, Threads>::HelpMarked(Info* op){ Node* other; if(op->p->right == op->l){ other = op->p->left; } else { other = op->p->right; } CASChild(op->gp, op->p, other); infos.publish(op->gp->update, 0); infos.publish(op, 1); CASPTR(&op->gp->update, Mark(op, DFLAG), Mark(op, CLEAN)); infos.releaseAll(); }
bool NBBST<T, Threads>::add(T value){ int key = hash(value); Node* newNode = newLeaf(key); SearchResult search; while(true){ Search(key, &search); nodes.publish(search.l, 0); infos.publish(search.p->update, 0); infos.publish(search.pupdate, 1); if(search.l->key == key){ nodes.releaseNode(newNode); nodes.releaseAll(); infos.releaseAll(); return false; //Key already in the set } if(getState(search.pupdate) != CLEAN){ Help(search.pupdate); } else { Node* newSibling = newLeaf(search.l->key); Node* newInt = newInternal(std::max(key, search.l->key)); newInt->update = Mark(nullptr, CLEAN); //Put the smaller child on the left if(newNode->key <= newSibling->key){ newInt->left = newNode; newInt->right = newSibling; } else { newInt->left = newSibling; newInt->right = newNode; } Info* op = newIInfo(search.p, newInt, search.l); infos.publish(op, 2); Update result = search.p->update; if(CASPTR(&search.p->update, search.pupdate, Mark(op, IFLAG))){ HelpInsert(op); if(search.pupdate){ infos.releaseNode(Unmark(search.pupdate)); } nodes.releaseAll(); infos.releaseAll(); return true; } else { nodes.releaseNode(newInt); nodes.releaseNode(newSibling); nodes.releaseAll(); infos.releaseNode(op); infos.releaseAll(); Help(result); } } } }