all: extend hash functions with an NMHashState argument

We often want to cascade hashing, meaning, to combine the
outcome of various hash functions in a larger hash.

Instead of having each hash function return a guint hash value,
accept a hash state argument. This saves the overhead of initializing
and completing the intermediate hash states.
It also avoids loosing entropy when we reduce the larger hash state
into the intermediate guint hash value.
This commit is contained in:
Thomas Haller
2017-10-17 11:53:08 +02:00
parent 2f56de7492
commit cfe8546df9
8 changed files with 415 additions and 516 deletions

View File

@@ -55,9 +55,9 @@ ASSERT_idx_type (const NMDedupMultiIdxType *idx_type)
nm_assert (idx_type);
#if NM_MORE_ASSERTS > 10
nm_assert (idx_type->klass);
nm_assert (idx_type->klass->idx_obj_id_hash);
nm_assert (idx_type->klass->idx_obj_id_hash_update);
nm_assert (idx_type->klass->idx_obj_id_equal);
nm_assert (!!idx_type->klass->idx_obj_partition_hash == !!idx_type->klass->idx_obj_partition_equal);
nm_assert (!!idx_type->klass->idx_obj_partition_hash_update == !!idx_type->klass->idx_obj_partition_equal);
nm_assert (idx_type->lst_idx_head.next);
#endif
}
@@ -181,13 +181,13 @@ _dict_idx_entries_hash (const NMDedupMultiEntry *entry)
_entry_unpack (entry, &idx_type, &obj, &lookup_head);
nm_hash_init (&h, 1914869417u);
if (idx_type->klass->idx_obj_partition_hash) {
if (idx_type->klass->idx_obj_partition_hash_update) {
nm_assert (obj);
nm_hash_update_val (&h, idx_type->klass->idx_obj_partition_hash (idx_type, obj));
idx_type->klass->idx_obj_partition_hash_update (idx_type, obj, &h);
}
if (!lookup_head)
nm_hash_update_val (&h, idx_type->klass->idx_obj_id_hash (idx_type, obj));
idx_type->klass->idx_obj_id_hash_update (idx_type, obj, &h);
nm_hash_update_val (&h, idx_type);
return nm_hash_complete (&h);
@@ -797,7 +797,11 @@ nm_dedup_multi_index_dirty_remove_idx (NMDedupMultiIndex *self,
static guint
_dict_idx_objs_hash (const NMDedupMultiObj *obj)
{
return obj->klass->obj_full_hash (obj);
NMHashState h;
nm_hash_init (&h, 1748638583u);
obj->klass->obj_full_hash_update (obj, &h);
return nm_hash_complete (&h);
}
static gboolean

View File

@@ -27,6 +27,8 @@
/*****************************************************************************/
struct _NMHashState;
typedef struct _NMDedupMultiObj NMDedupMultiObj;
typedef struct _NMDedupMultiObjClass NMDedupMultiObjClass;
typedef struct _NMDedupMultiIdxType NMDedupMultiIdxType;
@@ -69,9 +71,10 @@ struct _NMDedupMultiObjClass {
void (*obj_destroy) (NMDedupMultiObj *obj);
/* the NMDedupMultiObj can be deduplicated. For that the obj_full_hash()
/* the NMDedupMultiObj can be deduplicated. For that the obj_full_hash_update()
* and obj_full_equal() compare *all* fields of the object, even minor ones. */
guint (*obj_full_hash) (const NMDedupMultiObj *obj);
void (*obj_full_hash_update) (const NMDedupMultiObj *obj,
struct _NMHashState *h);
gboolean (*obj_full_equal) (const NMDedupMultiObj *obj_a,
const NMDedupMultiObj *obj_b);
};
@@ -152,8 +155,9 @@ void nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
struct _NMDedupMultiIdxTypeClass {
NMObjBaseClass parent;
guint (*idx_obj_id_hash) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj);
void (*idx_obj_id_hash_update) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj,
struct _NMHashState *h);
gboolean (*idx_obj_id_equal) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj_a,
const NMDedupMultiObj *obj_b);
@@ -167,8 +171,9 @@ struct _NMDedupMultiIdxTypeClass {
* object is not partitionable, it is never added to the NMDedupMultiIndex. */
gboolean (*idx_obj_partitionable) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj);
guint (*idx_obj_partition_hash) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj);
void (*idx_obj_partition_hash_update) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj,
struct _NMHashState *h);
gboolean (*idx_obj_partition_equal) (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj_a,
const NMDedupMultiObj *obj_b);