@@ -29,16 +29,18 @@ typedef void (*set_next_collision_t)(void *elem, h_index_t next_collision);
2929typedef bool (* compare_element_t )(const void * key_elem , const void * found_elem );
3030typedef bool (* element_is_empty_t )(const void * elem );
3131
32- static inline void * h_find (const void * table , h_index_t table_size ,
33- int hash_bits , size_t elem_size ,
34- const void * elem_to_find , hash_element_t hash_elem ,
35- get_next_collision_t get_next_collision ,
36- compare_element_t compare_elem ,
37- element_is_empty_t element_is_empty )
32+ static inline void *
33+ h_find (const void * table , h_index_t table_size , int hash_bits , size_t elem_size ,
34+ const void * elem_to_find , h_index_t * nb_collisions_followed ,
35+ hash_element_t hash_elem , get_next_collision_t get_next_collision ,
36+ compare_element_t compare_elem , element_is_empty_t element_is_empty )
3837{
3938 h_index_t curr_index , next_collision ;
4039 const void * curr_elem ;
4140
41+ if (nb_collisions_followed )
42+ * nb_collisions_followed = 0 ;
43+
4244 if (unlikely (table_size == 0 ))
4345 return NULL ;
4446
@@ -54,6 +56,8 @@ static inline void *h_find(const void *table, h_index_t table_size,
5456 next_collision = get_next_collision (curr_elem );
5557 while (next_collision != curr_index ) {
5658 curr_index = next_collision ;
59+ if (nb_collisions_followed )
60+ (* nb_collisions_followed )++ ;
5761 curr_elem = table + curr_index * elem_size ;
5862 if (compare_elem (elem_to_find , curr_elem ))
5963 return (void * )curr_elem ;
@@ -332,61 +336,74 @@ static inline void h_insert(struct h_insert_scratch *scratch, const void *elem,
332336 * empty (i.e. not used). Empty elements are not returned by find. If
333337 * the zero value of @elem_type is not "empty", the caller must set all
334338 * the slots to empty before using the table.
339+ * @trace_find: A function that traces the number of collisions
340+ * followed during a find operation, given paramemters:
341+ * const @elem_type *table,
342+ * h_index_t table_size,
343+ * int hash_bits,
344+ * const @elem_type *elem_to_find,
345+ * h_index_t *collisions_followed.
335346 */
336- #define DEFINE_COALESCED_HASH_TABLE (elem_type , table_func_prefix , key_member , \
337- next_collision_member , hash_expr , \
338- is_empty_expr ) \
339- static inline h_index_t table_func_prefix##_hash_elem( \
340- const void *_elem, h_index_t table_size, int hash_bits) \
341- { \
342- const elem_type *elem = _elem; \
343- return hash_expr; \
344- } \
345- static inline h_index_t table_func_prefix##_get_next_collision( \
346- const void *elem) \
347- { \
348- return ((const elem_type *)elem)->next_collision_member; \
349- } \
350- static inline void table_func_prefix##_set_next_collision( \
351- void *elem, h_index_t next_collision) \
352- { \
353- ((elem_type *)elem)->next_collision_member = next_collision; \
354- } \
355- static inline bool table_func_prefix##_compare_elem( \
356- const void *key_elem, const void *found_elem) \
357- { \
358- const elem_type *key = key_elem; \
359- const elem_type *found = found_elem; \
360- return key->key_member.data == found->key_member.data; \
361- } \
362- static inline bool table_func_prefix##_element_is_empty( \
363- const void *_elem) \
364- { \
365- const elem_type *elem = _elem; \
366- return is_empty_expr; \
367- } \
368- static inline const elem_type *table_func_prefix##_find( \
369- const elem_type *table, h_index_t table_size, int hash_bits, \
370- const elem_type *elem_to_find) \
371- { \
372- return h_find(table, table_size, hash_bits, sizeof(elem_type), \
373- elem_to_find, table_func_prefix##_hash_elem, \
374- table_func_prefix##_get_next_collision, \
375- table_func_prefix##_compare_elem, \
376- table_func_prefix##_element_is_empty); \
377- } \
378- static inline void table_func_prefix##_initialize( \
379- elem_type *table, h_index_t table_size) \
380- { \
381- h_initialize(table, table_size, sizeof(elem_type), \
382- table_func_prefix##_set_next_collision, \
383- table_func_prefix##_element_is_empty); \
384- } \
385- static inline void table_func_prefix##_insert( \
386- struct h_insert_scratch *scratch, const elem_type *elem) \
387- { \
388- h_insert(scratch, elem, table_func_prefix##_hash_elem, \
389- table_func_prefix##_get_next_collision, \
390- table_func_prefix##_set_next_collision, \
391- table_func_prefix##_element_is_empty); \
347+ #define DEFINE_COALESCED_HASH_TABLE (elem_type , table_func_prefix , key_member , \
348+ next_collision_member , hash_expr , \
349+ is_empty_expr , trace_find ) \
350+ static inline h_index_t table_func_prefix##_hash_elem( \
351+ const void *_elem, h_index_t table_size, int hash_bits) \
352+ { \
353+ const elem_type *elem = _elem; \
354+ return hash_expr; \
355+ } \
356+ static inline h_index_t table_func_prefix##_get_next_collision( \
357+ const void *elem) \
358+ { \
359+ return ((const elem_type *)elem)->next_collision_member; \
360+ } \
361+ static inline void table_func_prefix##_set_next_collision( \
362+ void *elem, h_index_t next_collision) \
363+ { \
364+ ((elem_type *)elem)->next_collision_member = next_collision; \
365+ } \
366+ static inline bool table_func_prefix##_compare_elem( \
367+ const void *key_elem, const void *found_elem) \
368+ { \
369+ const elem_type *key = key_elem; \
370+ const elem_type *found = found_elem; \
371+ return key->key_member.data == found->key_member.data; \
372+ } \
373+ static inline bool table_func_prefix##_element_is_empty( \
374+ const void *_elem) \
375+ { \
376+ const elem_type *elem = _elem; \
377+ return is_empty_expr; \
378+ } \
379+ static inline const elem_type *table_func_prefix##_find( \
380+ const elem_type *table, h_index_t table_size, int hash_bits, \
381+ const elem_type *elem_to_find) \
382+ { \
383+ h_index_t collisions_followed; \
384+ const elem_type *result = h_find( \
385+ table, table_size, hash_bits, sizeof(elem_type), \
386+ elem_to_find, &collisions_followed, \
387+ table_func_prefix##_hash_elem, \
388+ table_func_prefix##_get_next_collision, \
389+ table_func_prefix##_compare_elem, \
390+ table_func_prefix##_element_is_empty); \
391+ trace_find(table, table_size, hash_bits, elem_to_find, \
392+ collisions_followed); \
393+ return result; \
394+ } \
395+ static inline void table_func_prefix##_initialize( \
396+ elem_type *table, h_index_t table_size) \
397+ { \
398+ h_initialize(table, table_size, sizeof(elem_type), \
399+ table_func_prefix##_set_next_collision, \
400+ table_func_prefix##_element_is_empty); \
401+ } \
402+ static inline void table_func_prefix##_insert( \
403+ struct h_insert_scratch *scratch, const elem_type *elem) \
404+ { \
405+ h_insert(scratch, elem, table_func_prefix##_hash_elem, \
406+ table_func_prefix##_get_next_collision, \
407+ table_func_prefix##_set_next_collision, \
408+ table_func_prefix##_element_is_empty); \
392409 }
0 commit comments