예제 #1
0
int remove_node(marked_ptr_t* head, hash_key_t key)
{
    marked_ptr_t cur;
    marked_ptr_t* prev;

    while(1)
    {
        if(lf_table_find(head, key, &prev, &cur) == NULL)
        {
            return 0;
        }

        if (CAS(prev, CONSTRUCT(0, cur), CONSTRUCT(1, cur)) != CONSTRUCT(0, cur)) {continue;}
        if (CAS(prev, CONSTRUCT(1, cur), PTR_OF(cur)->next) == CONSTRUCT(1, cur))
        {
            free(PTR_OF(cur)); // problem here
        }
        else
        {
            lf_table_find(head, key, NULL, NULL); // use find to remove the marked node
        }

        return 1;
    }
}
예제 #2
0
void* lf_table_put_if_absent(LF_HashTable* table, void* key, void* value)
{
    marked_ptr_t* prev;
    marked_ptr_t cur;
    marked_ptr_t new_node;
    uint32_t index;

    index = HASH(key);
    while(1)
    {
        if(lf_table_find(&table->buckets[index], CONSTRUCT(0, key), &prev, &cur) != NULL)
        {
            return PTR_OF(cur)->value;
        }

        new_node = CONSTRUCT(0, malloc(sizeof(Node)));

        PTR_OF(new_node)->value = value;
        PTR_OF(new_node)->key = CONSTRUCT(0, key);

        PTR_OF(new_node)->next = *prev;
        if(CAS(prev, cur, CONSTRUCT(0, new_node)) == cur)
        {
            break;
        }
    }

    INCR(&table->size, 1);
    return NULL;
}
예제 #3
0
static list_entry *qt_dictionary_iterator_next_element(qt_dictionary_iterator *it)
{
    if((it == NULL) || (it->dict == NULL)) {
        return ERROR;
    }
    qt_dictionary *h = it->dict;
    if(h->count == 0) {
        it->bkt = 1;
        return NULL;
    }
    if(it->bkt == -1) {
        int csize = h->size, bucket;
        for(bucket = 0; bucket < csize; bucket++)
            if (h->B[bucket] != UNINITIALIZED) {
                it->bkt = 1;
                it->crt = PTR_OF(h->B[bucket]);
                return it->crt;
            }
    }
    if(it->crt == UNINITIALIZED) {
        return NULL;
    }
    it->crt = PTR_OF(it->crt->next);
    return it->crt;
}
예제 #4
0
static int qt_lf_list_delete(marked_ptr_t        *head,
                             so_key_t             hashed_key,
                             qt_key_t             key,
                             qt_dict_key_equals_f op_equals,
                             qt_dict_cleanup_f    cleanup)
{
    while (1) {
        marked_ptr_t *lprev;
        marked_ptr_t  lcur;
        marked_ptr_t  lnext;
        if (qt_lf_list_find(head, hashed_key, key, &lprev, &lcur, &lnext, op_equals) == NULL) {
            qthread_debug(ALWAYS_OUTPUT, "### inside delete - return 0\n");
            return 0;
        }
        if (qthread_cas_ptr(&PTR_OF(lcur)->next, (void*)CONSTRUCT(0, lnext), (void*)CONSTRUCT(1, lnext)) != (void *)CONSTRUCT(0, lnext)) {
            qthread_debug(ALWAYS_OUTPUT, "### inside delete - cas failed continue\n");
            continue;
        }
        if (qthread_cas(lprev, CONSTRUCT(0, lcur), CONSTRUCT(0, lnext)) == CONSTRUCT(0, lcur)) {
            if (cleanup != NULL) {
                cleanup(PTR_OF(lcur)->key, NULL);
            }
            qpool_free(hash_entry_pool, PTR_OF(lcur));
        } else {
            qt_lf_list_find(head, hashed_key, key, NULL, NULL, NULL, op_equals);                                   // needs to set cur/prev/next
        }
        return 1;
    }
}
예제 #5
0
파일: avl_test.c 프로젝트: powerhi/avl
static void prepare_for_dump_l(L_NODE *l_root, int idx, void **data_v, int *bal_v)
{
   data_v[idx] = l_root->data;
   if (IS_DEEPER(l_root->left)) {
      bal_v[idx] = IS_DEEPER(l_root->right) ? -2 : -1;
   } else {
      bal_v[idx] = IS_DEEPER(l_root->right) ?  1 :  0;
   }
   if (l_root->left)  prepare_for_dump_l(PTR_OF(l_root->left ), idx << 1    , data_v, bal_v);
   if (l_root->right) prepare_for_dump_l(PTR_OF(l_root->right), idx << 1 | 1, data_v, bal_v);
}
예제 #6
0
/**
 * Insert node "node" in the list starting at position "head".
 * Set "ocur" to be the item with the same key if it exists
 *      or the item which follows if the node was added successfully.
 * Set crt_node to point to the current node with key = "node->key"
 * Return 0 if item existed and 1 if it was inserted
 */
static int qt_lf_list_insert(marked_ptr_t        *head,
                             hash_entry          *node,
                             marked_ptr_t        *ocur,
                             hash_entry         **crt_node,
                             qt_dict_key_equals_f op_equals)
{
    so_key_t hashed_key = node->hashed_key;
    qt_key_t key        = node->key;

    while (1) {
        marked_ptr_t *lprev;
        marked_ptr_t  cur;

        if (qt_lf_list_find(head, hashed_key, key, &lprev, &cur, NULL, op_equals) != NULL) {                       // needs to set cur/prev
            if (ocur) { *ocur = cur; }
            if (crt_node) { *crt_node = PTR_OF(cur); }
            return 0;
        }
        node->next = (hash_entry *)CONSTRUCT(0, cur);
        if (qthread_cas(lprev, (marked_ptr_t)(uintptr_t)node->next, CONSTRUCT(0, node)) == CONSTRUCT(0, cur)) {
            if (ocur) { *ocur = cur; }
            if (crt_node) { *crt_node = node; }
            return 1;
        }
    }
}
예제 #7
0
파일: avl_test.c 프로젝트: powerhi/avl
static int depth_l(L_NODE *root, bool check)
{
   int depth_left, depth_right;

   depth_left  = root->left  ? depth_l(PTR_OF(root->left ), check) : 0;
   depth_right = root->right ? depth_l(PTR_OF(root->right), check) : 0;
   if (check) {
      assert(depth_left  <= depth_right + 1);
      assert(depth_right <= depth_left  + 1);
      if (depth_left > depth_right) {
         assert(  IS_DEEPER(root->left ));
         assert( !IS_DEEPER(root->right));
      } else if (depth_left < depth_right) {
         assert( !IS_DEEPER(root->left ));
         assert(  IS_DEEPER(root->right));
      } else {
         assert( !IS_DEEPER(root->left ));
         assert( !IS_DEEPER(root->right));
      }
   }
   return (depth_left > depth_right ? depth_left : depth_right) + 1;
}
예제 #8
0
파일: avl_test.c 프로젝트: powerhi/avl
void avl_dump_w_ctx(TREE *tree, void (*callback)(void *data, int idx, int bal, void *context), void *context)
{
   if (tree->root) {
      int    max_depth = 0;
      int    idx, idx_top;
      void **data_v;
      int   *bal_v;

      if (IS_X(tree)) max_depth = depth_x(PTR_OF(tree->x_root), false);
      else            max_depth = depth_l(PTR_OF(tree->l_root), false);
      idx_top = 1 << max_depth;
      data_v = calloc(idx_top, sizeof(void*));
      bal_v  = calloc(idx_top, sizeof(int));
      if (IS_X(tree)) prepare_for_dump_x(PTR_OF(tree->x_root), 1, data_v, bal_v);
      else            prepare_for_dump_l(PTR_OF(tree->l_root), 1, data_v, bal_v);
      for (idx = 1; idx < idx_top; idx++) {
         (*callback)(data_v[idx], idx, bal_v[idx], context);
      }
      free(data_v);
      free(bal_v);
   } else {
      (*callback)(NULL, 1, 0, context);
   }
}
예제 #9
0
// old public method
static inline void qt_hash_destroy(qt_hash h)
{
    marked_ptr_t cursor;

    assert(h);
    assert(h->B);
    cursor = h->B[0];
    while (PTR_OF(cursor) != NULL) {
        marked_ptr_t tmp = cursor;
        assert(MARK_OF(tmp) == 0);
        cursor = (marked_ptr_t)((PTR_OF(cursor)->next));
        if (h->op_cleanup && ((PTR_OF(tmp)->key || PTR_OF(tmp)->value))) {
            // only call the cleanup function on non-place-holders
            h->op_cleanup(PTR_OF(tmp)->key, PTR_OF(tmp)->value);
        }
        qpool_free(hash_entry_pool, PTR_OF(tmp));
    }
    FREE(h->B, hard_max_buckets * sizeof(marked_ptr_t));
    FREE(h, sizeof(qt_hash));
}
예제 #10
0
static void initialize_bucket(qt_hash h,
                              size_t  bucket)
{
    size_t       parent = GET_PARENT(bucket);
    marked_ptr_t cur;

    if (h->B[parent] == UNINITIALIZED) {
        initialize_bucket(h, parent);
    }
    hash_entry *dummy = qpool_alloc(hash_entry_pool);
    assert(dummy);
    dummy->hashed_key = so_dummykey(bucket);
    dummy->key        = NULL;
    dummy->value      = NULL;
    dummy->next       = (hash_entry*)UNINITIALIZED;
    if (!qt_lf_list_insert(&(h->B[parent]), dummy, &cur, NULL, h->op_equals)) {
        qpool_free(hash_entry_pool, dummy);
        dummy = PTR_OF(cur);
        while (h->B[bucket] != CONSTRUCT(0, dummy)) ;
    } else {
        h->B[bucket] = CONSTRUCT(0, dummy);
    }
}
예제 #11
0
void* lf_table_find(marked_ptr_t* head, hash_key_t key, marked_ptr_t** prev, marked_ptr_t* cur)
{
    marked_ptr_t* tp_prev;
    marked_ptr_t tp_cur;
    marked_ptr_t* tp_next;

    hash_key_t cur_key;
    void* cur_value;

    if(PTR_OF(*head) == NULL)
    {
        if(prev) {*prev = head;};
        if(cur){*cur = *head;};

        return NULL;
    }

    while(1)
    {
        tp_prev = head;
        tp_cur = *head;

        while(1)
        {
            if (PTR_OF(tp_cur) == NULL)
            {
                if(prev){*prev = tp_prev;};
                if(cur){*cur = tp_cur;};

                return NULL;
            }

            tp_next = &PTR_OF(tp_cur)->next;

            cur_key = PTR_OF(tp_cur)->key;
            cur_value = PTR_OF(tp_cur)->value;

            if(*tp_prev != tp_cur)
            {
                break; // someone has mucked with the list, start over
            }

            if(MARK_OF(tp_cur))
            {
                if (CAS(tp_prev, CONSTRUCT(1, tp_cur), tp_next) == CONSTRUCT(1, tp_cur)) {
                    free(PTR_OF(tp_cur));

                    tp_cur = *tp_next;
                    continue;
                } else {
                    break; //start over
                }
            }

            if (key >= cur_key)
            {
                if(prev){*prev = tp_prev;};
                if(cur){*cur = tp_cur;};

                return key == cur_key ? cur_value : NULL;
            }

            tp_prev = tp_next;
            tp_cur = *tp_next;
        }
    }
}
예제 #12
0
static void *qt_lf_list_find(marked_ptr_t        *head,
                             so_key_t             hashed_key,
                             qt_key_t             key,
                             marked_ptr_t       **oprev,
                             marked_ptr_t        *ocur,
                             marked_ptr_t        *onext,
                             qt_dict_key_equals_f op_equals)
{
    so_key_t      ckey;
    qt_key_t      okey;
    void         *cval;
    marked_ptr_t *prev = NULL;
    marked_ptr_t  cur  = UNINITIALIZED;
    marked_ptr_t  next = UNINITIALIZED;

    // int foundInsertPos = 0;
    while (1) {
        prev = head;
        cur  = *prev;
        while (1) {
            if (PTR_OF(cur) == NULL) {
                if (oprev) { *oprev = prev; }
                if (ocur) { *ocur = cur; }
                if (onext) { *onext = next; }
                return 0;
            }
            next = (marked_ptr_t)(PTR_OF(cur)->next);
            ckey = PTR_OF(cur)->hashed_key;
            cval = PTR_OF(cur)->value;
            okey = PTR_OF(cur)->key;
            if (*prev != CONSTRUCT(0, cur)) {
                break; // this means someone mucked with the list; start over
            }
            if (!MARK_OF(next)) {  // if next pointer is not marked
                if (ckey >= hashed_key) {
                    // if current key > hashed_key, the key isn't in the list; if current key == hashed_key, the key IS in the list
                    // if (foundInsertPos == 0) {
                    if (oprev) { *oprev = prev; }
                    if (ocur) { *ocur = cur; }
                    if (onext) { *onext = next; }
                    // foundInsertPos = 1;
                    // }

                    if(ckey == hashed_key) {
                        if((okey != NULL) && op_equals(okey, key)) {
                            /*
                             * if (oprev) { *oprev = prev; }
                             * if (ocur) { *ocur = cur; }
                             * if (onext) { *onext = next; }
                             */
                            return cval;
                        }                        // else, keep looking
                    } else { return NULL; }
                }
                // but if current key < hashed_key, the we don't know yet, keep looking
                prev = (marked_ptr_t *)&(PTR_OF(cur)->next);
            } else {
                if (qthread_cas(prev, CONSTRUCT(0, cur), CONSTRUCT(0, next)) == CONSTRUCT(0, cur)) {
                    qpool_free(hash_entry_pool, PTR_OF(cur));
                } else {
                    break;
                }
            }
            cur = next;
        }
    }
}