Example #1
0
  int
fraser_remove(sl_intset_t *set, slkey_t key, val_t *val, int remove_succ)
{
  sl_node_t **succs;
  int result;

  /* succs = (sl_node_t **)malloc(*levelmax * sizeof(sl_node_t *)); */
  succs = (sl_node_t **)ssalloc(*levelmax * sizeof(sl_node_t *));
  fraser_search(set, key, NULL, succs);

  if (remove_succ) {
    result = (succs[0]->next[0] != NULL); // Don't remove tail
    key = succs[0]->key;
    *val = succs[0]->val;
  } else {
    result = (succs[0]->key == key);
    *val = succs[0]->val;
  }

  if (result == 0)
    goto end;
  /* 1. Node is logically deleted when the deleted field is not 0 */
  if (succs[0]->deleted)
  {
    result = 0;
    goto end;
  }


  if (ATOMIC_FETCH_AND_INC_FULL(&succs[0]->deleted) == 0)
  {
    /* 2. Mark forward pointers, then search will remove the node */
    mark_node_ptrs(succs[0]);

    /* MEM_BARRIER; */

    fraser_search(set, key, NULL, NULL);
  }
  else
  {
    result = 0;
  }  
end:
  /* free(succs); */
  ssfree(succs);

  return result;
}
Example #2
0
int fraser_remove(sl_intset_t *set, val_t val) {
  sl_node_t **succs;
  int result;

  succs = (sl_node_t **)malloc(levelmax * sizeof(sl_node_t *));
  fraser_search(set, val, NULL, succs);
  result = (succs[0]->val == val);
  if (result == 0)
    goto end;
  /* 1. Node is logically deleted when the deleted field is not 0 */
  if (succs[0]->deleted) {
    result = 0;
    goto end;
  }
  ATOMIC_FETCH_AND_INC_FULL(&succs[0]->deleted);
  /* 2. Mark forward pointers, then search will remove the node */
  mark_node_ptrs(succs[0]);
  fraser_search(set, val, NULL, NULL);    
end:
  free(succs);

  return result;
}
Example #3
0
int naive_delete_min(sl_intset_t *set, val_t *val, thread_data_t *d) {
  sl_node_t *first;
  int result;

  first = set->head;

  while(1) {
    do {
      first = (sl_node_t*)unset_mark((uintptr_t)first->next[0]);
    } while(first->next[0] && first->deleted);
   if (ATOMIC_FETCH_AND_INC_FULL(&first->deleted) != 0) {
     d->nb_collisions++;
   } else {
     break;
   }
  }

  result = (first->next[0] != NULL);
  if (!result) {
    return 1;
  }
  
  *val = (first->val);
  mark_node_ptrs(first);

  // unsigned int *seed = &d->seed2;
  // *seed = _MarsagliaXOR(*seed);
  // if (*seed % (d->nb_threads) == 0) {
  //   fraser_search(set, first->val, NULL, NULL);    
  // }

  if (!first->next[0]->deleted)
     fraser_search(set, first->val, NULL, NULL);    

  return result; 
}
Example #4
0
int spray_delete_min(sl_intset_t *set, val_t *val, thread_data_t *d) {
  unsigned int n = d->nb_threads;
  unsigned int *seed = &d->seed2;

#ifndef DISTRIBUTION_EXPERIMENT 
  *seed = _MarsagliaXOR(*seed);
  if (n == 1 || *seed % n/*/floor_log_2(n)*/ == 0) { // n == 1 is equivalent to naive delete_min
    d->nb_clean++;
    return naive_delete_min(set, val, d);
  }
#endif

  sl_node_t *cur;
  int result;
  int scanlen;
  int height = SCANHEIGHT; 
  int scanmax = SCANMAX;
  int scan_inc = SCANINC;

  cur = set->head;

  int i = height;
  int dummy = 0;
  while(1) {
    *seed = _MarsagliaXOR(*seed);
    scanlen = *seed % (scanmax+1); 

    while (dummy < n*floor_log_2(n)/2 && scanlen > 0) {
      dummy += (1 << i);
      scanlen--;
    }


    while (scanlen > 0 && cur->next[i]) { // Step right //here: cur->next[0], or cur->next[i]??
      cur = (sl_node_t*)unset_mark((uintptr_t)cur->next[i]);
      if (!cur->deleted) scanlen--;
    } 

    // TODO: This is probably a reasonable condition to become a 'cleaner' since the list is so small
    //       We can also just ignore it since it shouldn't happen in benchmarks?
    if (!cur->next[0]) return 0; //got to end of list

    scanmax += scan_inc;

    if (i == 0) break;
    if (i <= SCANSKIP) { i = 0; continue; } // need to guarantee bottom level gets scanned
    i -= SCANSKIP;
  }

  if (cur == set->head) // still in dummy range
    return 0; // TODO: clean instead? something else?

  while (cur->deleted && cur->next[0]) {
    cur = (sl_node_t*)unset_mark((uintptr_t)cur->next[0]); // Find first non-deleted node
  } 

  if (!cur->next[0]) return 0;

#ifdef DISTRIBUTION_EXPERIMENT 
  *val = (cur->val);
  return 1;
#endif

  result = 1;
  if (cur->deleted == 0 )
  {
    result = ATOMIC_FETCH_AND_INC_FULL(&cur->deleted);
  }
  if (result != 0) {
    d->nb_collisions++;  
    return 0; // TODO: Retry and eventually 'clean'
  }

  *val = (cur->val);
  mark_node_ptrs(cur);

  // if (((*seed) & 0x10)) return 1;  

  // TODO: batch deletes (this method is somewhat inefficient)
  // fraser_search(set, cur->val, NULL, NULL);

  return 1; 
}