Esempio n. 1
0
// Safe to call on different entries at the same time
// NOT safe to do find() whilst doing delete()
void hash_table_delete(HashTable *const ht, hkey_t pos)
{
  uint64_t bucket = pos / ht->bucket_size;

  ctx_assert(pos != HASH_NOT_FOUND);
  ctx_assert(ht->buckets[bucket][HT_BITEMS] > 0);
  ctx_assert(ht->num_kmers > 0);
  ctx_assert(HASH_ENTRY_ASSIGNED(ht->table[pos]));

  ht->table[pos] = unset_bkmer;
  __sync_fetch_and_sub((volatile uint8_t *)&ht->buckets[bucket][HT_BITEMS], 1);
  __sync_fetch_and_sub((volatile uint64_t *)&ht->num_kmers, 1);

  ctx_assert(!HASH_ENTRY_ASSIGNED(ht->table[pos]));
}
Esempio n. 2
0
// Safe to call on different entries at the same time
// NOT safe to do find() whilst doing delete()
void hash_table_delete(HashTable *const ht, hkey_t pos)
{
  uint64_t bucket = pos / ht->bucket_size, n, m;

  ctx_assert(pos != HASH_NOT_FOUND);
  ctx_assert(HASH_ENTRY_ASSIGNED(ht->table[pos]));

  memset(ht->table+pos, 0, sizeof(BinaryKmer));
  n = __sync_fetch_and_sub((volatile uint64_t *)&ht->num_kmers, 1);
  m = __sync_fetch_and_sub((volatile uint8_t *)&ht->buckets[bucket][HT_BITEMS], 1);

  ctx_assert2(n > 0, "Deleted from empty table");
  ctx_assert2(m > 0, "Deleted from empty bucket");
  ctx_assert(!HASH_ENTRY_ASSIGNED(ht->table[pos]));
}
Esempio n. 3
0
void hash_table_empty(HashTable *const ht)
{
  memset(ht->table, 0, ht->capacity * sizeof(BinaryKmer));
  memset(ht->buckets, 0, ht->num_of_buckets * sizeof(uint8_t[2]));

  HashTable data = {
    .table = ht->table,
    .num_of_buckets = ht->num_of_buckets,
    .hash_mask = ht->hash_mask,
    .bucket_size = ht->bucket_size,
    .capacity = ht->capacity,
    .buckets = ht->buckets,
    .num_kmers = 0,
    .collisions = {0}};

  memcpy(ht, &data, sizeof(data));
}

static inline const BinaryKmer* hash_table_find_in_bucket(const HashTable *const ht,
                                                          uint_fast32_t bucket,
                                                          BinaryKmer bkmer)
{
  const BinaryKmer *ptr = ht_bckt_ptr(ht, bucket);
  const BinaryKmer *end = ptr + hash_table_bsize(ht, bucket);
  bkmer.b[0] |= BKMER_SET_FLAG; // mark as assigned in the hash table

  while(ptr < end) {
    if(binary_kmer_eq(bkmer, *ptr)) return ptr;
    ptr++;
  }
  return NULL; // Not found
}

// Remember to increment ht->num_kmers
static inline BinaryKmer* hash_table_insert_in_bucket(HashTable *ht,
                                                      uint_fast32_t bucket,
                                                      BinaryKmer bkmer)
{
  size_t bsize = hash_table_bsize(ht, bucket);
  size_t bitems = hash_table_bitems(ht, bucket);
  ctx_assert(bitems < ht->bucket_size);
  ctx_assert(bitems <= bsize);
  BinaryKmer *ptr = ht_bckt_ptr(ht, bucket);
  bkmer.b[0] |= BKMER_SET_FLAG; // mark as assigned in the hash table

  if(bitems == bsize) {
    ptr += bsize;
    ht->buckets[bucket][HT_BSIZE]++;
  }
  else {
    // Find an entry that has been deleted from this bucket previously
    while(HASH_ENTRY_ASSIGNED(*ptr)) ptr++;
  }

  *ptr = bkmer;
  ht->buckets[bucket][HT_BITEMS]++;
  return ptr;
}
Esempio n. 4
0
void hash_table_empty(HashTable *const ht)
{
  size_t i;
  BinaryKmer *table = ht->table;
  for(i = 0; i < ht->capacity; i++) table[i] = unset_bkmer;
  memset(ht->buckets, 0, ht->num_of_buckets * sizeof(uint8_t[2]));

  HashTable data = {
    .table = ht->table,
    .num_of_buckets = ht->num_of_buckets,
    .hash_mask = ht->hash_mask,
    .bucket_size = ht->bucket_size,
    .capacity = ht->capacity,
    .buckets = ht->buckets,
    .num_kmers = 0,
    .collisions = {0}};

  memcpy(ht, &data, sizeof(data));
}

static inline const BinaryKmer* hash_table_find_in_bucket_mt(const HashTable *const ht,
                                                             uint_fast32_t bucket,
                                                             const BinaryKmer bkmer)
{
  const BinaryKmer *ptr = ht_bckt_ptr(ht, bucket);
  const BinaryKmer *end = ptr + *(volatile __typeof(ht->buckets[0][0])*)&ht->buckets[bucket][HT_BSIZE];

  while(ptr < end) {
    BinaryKmer tgt = *(volatile const BinaryKmer*)ptr;
    if(binary_kmers_are_equal(bkmer, tgt)) return ptr;
    ptr++;
  }
  return NULL; // Not found
}

/*
static inline
const BinaryKmer* hash_table_find_insert_in_bucket(const HashTable *const ht,
                                                   uint_fast32_t bucket,
                                                   const BinaryKmer bkmer,
                                                   bool *found)
{
  const BinaryKmer *ptr = ht_bckt_ptr(ht, bucket);
  const BinaryKmer *end = ptr + ht->buckets[bucket][HT_BSIZE];
  const BinaryKmer *empty = NULL;

  for(; ptr < end && !binary_kmers_are_equal(bkmer, *ptr); ptr++) {
    if(!HASH_ENTRY_ASSIGNED(*ptr)) empty = ptr;
  }

  *found = (ptr < end);

  if(ptr == end && empty == NULL &&
     ht->buckets[bucket][HT_BSIZE] < ht->bucket_size)
  {
    *empty = bkmer;
    ht->num_kmers++;
    ht->buckets[bucket][HT_BITEMS]++;
    ht->buckets[bucket][HT_BSIZE]++;
  }

  return ptr < end ? ptr : empty;
}

// Code to find/insert:
// h = binary_kmer_hash(key,ht->seed+i) & ht->hash_mask;
// ptr = hash_table_find_insert_in_bucket(ht, h, key, &f);
// if(ptr != NULL) {
//   *found = f;
//   return ptr;
// }
*/

// Remember to increment ht->num_kmers
static inline BinaryKmer* hash_table_insert_in_bucket(HashTable *ht,
                                                      uint_fast32_t bucket,
                                                      const BinaryKmer bkmer)
{
  ctx_assert(ht->buckets[bucket][HT_BITEMS] < ht->bucket_size);
  BinaryKmer *ptr = ht_bckt_ptr(ht, bucket);

  if(ht->buckets[bucket][HT_BSIZE] == ht->buckets[bucket][HT_BITEMS]) {
    ptr += ht->buckets[bucket][HT_BSIZE];
    ht->buckets[bucket][HT_BSIZE]++;
  }
  else {
    // Find an entry that has been deleted from this bucket previously
    while(HASH_ENTRY_ASSIGNED(*ptr)) ptr++;
  }

  *ptr = bkmer;
  ht->buckets[bucket][HT_BITEMS]++;
  return ptr;
}