in src/clds_hash_table.c [195:277]
CLDS_HASH_TABLE_HANDLE clds_hash_table_create(COMPUTE_HASH_FUNC compute_hash, KEY_COMPARE_FUNC key_compare_func, size_t initial_bucket_size, CLDS_HAZARD_POINTERS_HANDLE clds_hazard_pointers, volatile_atomic int64_t* start_sequence_number, HASH_TABLE_SKIPPED_SEQ_NO_CB skipped_seq_no_cb, void* skipped_seq_no_cb_context)
{
CLDS_HASH_TABLE_HANDLE clds_hash_table;
/* Codes_SRS_CLDS_HASH_TABLE_01_058: [ start_sequence_number shall be allowed to be NULL, in which case no sequence number computations shall be performed. ]*/
/* Codes_S_R_S_CLDS_HASH_TABLE_01_072: [ skipped_seq_no_cb shall be allowed to be NULL. ]*/
/* Codes_S_R_S_CLDS_HASH_TABLE_01_073: [ skipped_seq_no_cb_context shall be allowed to be NULL. ]*/
if (
/* Codes_SRS_CLDS_HASH_TABLE_01_003: [ If compute_hash is NULL, clds_hash_table_create shall fail and return NULL. ]*/
(compute_hash == NULL) ||
/* Codes_SRS_CLDS_HASH_TABLE_01_045: [ If key_compare_func is NULL, clds_hash_table_create shall fail and return NULL. ]*/
(key_compare_func == NULL) ||
/* Codes_SRS_CLDS_HASH_TABLE_01_004: [ If initial_bucket_size is 0, clds_hash_table_create shall fail and return NULL. ]*/
(initial_bucket_size == 0) ||
/* Codes_SRS_CLDS_HASH_TABLE_01_005: [ If clds_hazard_pointers is NULL, clds_hash_table_create shall fail and return NULL. ]*/
(clds_hazard_pointers == NULL) ||
/* Codes_S_R_S_CLDS_HASH_TABLE_01_074: [ If start_sequence_number is NULL, then skipped_seq_no_cb must also be NULL, otherwise clds_sorted_list_create shall fail and return NULL. ]*/
((start_sequence_number == NULL) && (skipped_seq_no_cb != NULL))
)
{
/* Codes_SRS_CLDS_HASH_TABLE_01_002: [ If any error happens, clds_hash_table_create shall fail and return NULL. ]*/
LogError("Invalid arguments: COMPUTE_HASH_FUNC compute_hash=%p, KEY_COMPARE_FUNC key_compare_func=%p, size_t initial_bucket_size=%zu, CLDS_HAZARD_POINTERS_HANDLE clds_hazard_pointers=%p, volatile_atomic int64_t* start_sequence_number=%p, HASH_TABLE_SKIPPED_SEQ_NO_CB skipped_seq_no_cb=%p, void* skipped_seq_no_cb_context=%p",
compute_hash, key_compare_func, initial_bucket_size, clds_hazard_pointers, start_sequence_number, skipped_seq_no_cb, skipped_seq_no_cb_context);
}
else
{
/* Codes_SRS_CLDS_HASH_TABLE_01_001: [ clds_hash_table_create shall create a new hash table object and on success it shall return a non-NULL handle to the newly created hash table. ]*/
clds_hash_table = malloc(sizeof(CLDS_HASH_TABLE));
if (clds_hash_table == NULL)
{
/* Codes_SRS_CLDS_HASH_TABLE_01_002: [ If any error happens, clds_hash_table_create shall fail and return NULL. ]*/
LogError("Cannot allocate memory for hash table");
}
else
{
/* Codes_SRS_CLDS_HASH_TABLE_01_027: [ The hash table shall maintain a list of arrays of buckets, so that it can be resized as needed. ]*/
clds_hash_table->first_hash_table = malloc_flex(sizeof(BUCKET_ARRAY), initial_bucket_size, sizeof(CLDS_SORTED_LIST_HANDLE));
if (clds_hash_table->first_hash_table == NULL)
{
LogError("Cannot allocate memory for hash table array. Failure in malloc_flex(sizeof(BUCKET_ARRAY)=%zu, initial_bucket_size=%zu, sizeof(CLDS_SORTED_LIST_HANDLE)=%zu);",
sizeof(BUCKET_ARRAY), initial_bucket_size, sizeof(CLDS_SORTED_LIST_HANDLE));
}
else
{
size_t i;
// all OK
clds_hash_table->clds_hazard_pointers = clds_hazard_pointers;
clds_hash_table->compute_hash = compute_hash;
clds_hash_table->key_compare_func = key_compare_func;
clds_hash_table->skipped_seq_no_cb = skipped_seq_no_cb;
clds_hash_table->skipped_seq_no_cb_context = skipped_seq_no_cb_context;
(void)interlocked_exchange(&clds_hash_table->pending_write_operations, 0);
(void)interlocked_exchange(&clds_hash_table->locked_for_write, 0);
/* Codes_SRS_CLDS_HASH_TABLE_01_057: [ start_sequence_number shall be used as the sequence number variable that shall be incremented at every operation that is done on the hash table. ]*/
clds_hash_table->sequence_number = start_sequence_number;
// set the initial bucket count
(void)interlocked_exchange_pointer((void* volatile_atomic*)&clds_hash_table->first_hash_table->next_bucket, NULL);
(void)interlocked_exchange(&clds_hash_table->first_hash_table->bucket_count, (int32_t)initial_bucket_size);
(void)interlocked_exchange(&clds_hash_table->first_hash_table->item_count, 0);
(void)interlocked_exchange(&clds_hash_table->first_hash_table->pending_insert_count, 0);
for (i = 0; i < initial_bucket_size; i++)
{
(void)interlocked_exchange_pointer((void* volatile_atomic*)&clds_hash_table->first_hash_table->hash_table[i], NULL);
}
goto all_ok;
}
free(clds_hash_table);
}
}
clds_hash_table = NULL;
all_ok:
return clds_hash_table;
}