setval_t set_remove(set_t *s, setkey_t k) { node_t *f, *w; qnode_t qn[4], *pqn[] = { qn+0, qn+1, qn+2, qn+3, qn+0, qn+1 }; int dir; setval_t v = NULL; ptst_t *ptst; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); f = find(&s->root, k, pqn[0], &dir); if ( (w = FOLLOW(f, dir)) != NULL ) { LOCK(w, pqn[1]); v = w->v; w->v = NULL; assert(!IS_BLUE(w)); delete_by_rotation(ptst, f, dir, pqn, 0); } else { UNLOCK(f, pqn[0]); } critical_exit(ptst); return v; }
setval_t set_remove(set_t *s, setkey_t k) { ptst_t *ptst; node_t *y, *z; qnode_t z_qn; setval_t ov = NULL; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); z = &s->root; while ( (y = (k <= z->k) ? z->l : z->r) != NULL ) z = y; if ( z->k == k ) { mcs_lock(&z->lock, &z_qn); if ( !IS_GARBAGE(z) ) { ov = GET_VALUE(z->v); SET_VALUE(z->v, NULL); } mcs_unlock(&z->lock, &z_qn); } if ( ov != NULL ) delete_finish(ptst, z); critical_exit(ptst); return ov; }
setval_t set_lookup(set_t *s, setkey_t k) { node_t *n; setval_t v = NULL; ptst_t *ptst; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); n = weak_find(&s->root, k); if ( n != NULL ) v = GET_VALUE(n); critical_exit(ptst); return v; }
setval_t set_lookup(set_t *s, setkey_t k) { ptst_t *ptst; node_t *m, *n; setval_t v; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); n = &s->root; while ( (m = (k <= n->k) ? n->l : n->r) != NULL ) n = m; v = (k == n->k) ? GET_VALUE(n->v) : NULL; if ( v == GARBAGE_VALUE ) v = NULL; critical_exit(ptst); return v; }
setval_t set_update(set_t *s, setkey_t k, setval_t v, int overwrite) { node_t *f, *w; qnode_t f_qn, w_qn; int dir; setval_t ov = NULL; ptst_t *ptst; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); retry: f = find(&s->root, k, &f_qn, &dir); if ( (w = FOLLOW(f, dir)) != NULL ) { /* Protected by parent lock. */ assert(!IS_BLUE(w)); ov = w->v; if ( overwrite || (ov == NULL) ) w->v = v; } else { w = gc_alloc(ptst, gc_id); w->l = NULL; w->r = NULL; w->v = v; w->k = k; mcs_init(&w->lock); UPDATE(f, dir, w); } UNLOCK(f, &f_qn); critical_exit(ptst); return ov; }
s->root.r = NULL; s->root.p = NULL; s->root.copy = 0; return s; } setval_t set_update(set_t *s, setkey_t k, setval_t v, int overwrite) { node_t *a, *new; qnode_t qn; setval_t ov = NULL; ptst_t *ptst; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); a = strong_search(&s->root, k, &qn); if ( a->k != k ) { new = gc_alloc(ptst, gc_id); mcs_init(&new->lock); new->k = k; new->v = v; new->l = NULL; new->r = NULL; new->p = a; new->copy = 0; if ( a->k < k ) a->r = new; else a->l = new;
setval_t set_update(set_t *s, setkey_t k, setval_t v, int overwrite) { ptst_t *ptst; qnode_t y_qn, z_qn; node_t *y, *z, *new_internal, *new_leaf; int fix_up = 0; setval_t ov = NULL; k = CALLER_TO_INTERNAL_KEY(k); ptst = critical_enter(); retry: z = &s->root; while ( (y = (k <= z->k) ? z->l : z->r) != NULL ) z = y; y = z->p; mcs_lock(&y->lock, &y_qn); if ( (((k <= y->k) ? y->l : y->r) != z) || IS_GARBAGE(y) ) { mcs_unlock(&y->lock, &y_qn); goto retry; } mcs_lock(&z->lock, &z_qn); assert(!IS_GARBAGE(z) && IS_LEAF(z)); if ( z->k == k ) { ov = GET_VALUE(z->v); if ( overwrite || (ov == NULL) ) SET_VALUE(z->v, v); } else { new_leaf = gc_alloc(ptst, gc_id); new_internal = gc_alloc(ptst, gc_id); new_leaf->k = k; new_leaf->v = MK_BLACK(v); new_leaf->l = NULL; new_leaf->r = NULL; new_leaf->p = new_internal; mcs_init(&new_leaf->lock); if ( z->k < k ) { new_internal->k = z->k; new_internal->l = z; new_internal->r = new_leaf; } else { new_internal->k = k; new_internal->l = new_leaf; new_internal->r = z; } new_internal->p = y; mcs_init(&new_internal->lock); if ( IS_UNBALANCED(z->v) ) { z->v = MK_BALANCED(z->v); new_internal->v = MK_BLACK(INTERNAL_VALUE); } else if ( IS_RED(y->v) ) { new_internal->v = MK_UNBALANCED(MK_RED(INTERNAL_VALUE)); fix_up = 1; } else { new_internal->v = MK_RED(INTERNAL_VALUE); } WMB(); z->p = new_internal; if ( y->l == z ) y->l = new_internal; else y->r = new_internal; } mcs_unlock(&y->lock, &y_qn); mcs_unlock(&z->lock, &z_qn); if ( fix_up ) fix_unbalance_up(ptst, new_internal); out: critical_exit(ptst); return ov; }