add hash function BLI_ghash_assign, BLI_edgehash_assign
avoids remove,insert and only hashes the key once.
This commit is contained in:
parent
7cce556344
commit
754b4ab3bc
@ -100,11 +100,13 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
|
||||
bPoseChannel *chan;
|
||||
|
||||
for (chan = pose->chanbase.first; chan; chan = chan->next) {
|
||||
void **val_p;
|
||||
if (chan->bone->flag & BONE_NO_DEFORM)
|
||||
continue;
|
||||
|
||||
if (BLI_ghash_remove(gh, chan->name, NULL, NULL)) {
|
||||
BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1));
|
||||
val_p = BLI_ghash_lookup_p(gh, chan->name);
|
||||
if (val_p) {
|
||||
*val_p = SET_INT_IN_POINTER(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -367,12 +367,12 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
|
||||
BLI_assert(current_owner != new_owner);
|
||||
|
||||
/* Remove current ownership */
|
||||
BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
|
||||
// BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); // assign handles below
|
||||
BLI_ghash_remove(current_owner->bm_unique_verts, v, NULL, NULL);
|
||||
|
||||
/* Set new ownership */
|
||||
BLI_ghash_insert(bvh->bm_vert_to_node, v,
|
||||
SET_INT_IN_POINTER(new_owner - bvh->nodes));
|
||||
BLI_ghash_assign(bvh->bm_vert_to_node, v,
|
||||
SET_INT_IN_POINTER(new_owner - bvh->nodes), NULL, NULL);
|
||||
BLI_ghash_insert(new_owner->bm_unique_verts, v, NULL);
|
||||
BLI_ghash_remove(new_owner->bm_other_verts, v, NULL, NULL);
|
||||
BLI_assert(!BLI_ghash_haskey(new_owner->bm_other_verts, v));
|
||||
|
@ -43,6 +43,7 @@ enum {
|
||||
EdgeHash *BLI_edgehash_new(void);
|
||||
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp);
|
||||
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val);
|
||||
void BLI_edgehash_assign(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val);
|
||||
void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1);
|
||||
void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1);
|
||||
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1);
|
||||
|
@ -59,6 +59,7 @@ enum {
|
||||
GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info);
|
||||
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
|
||||
void BLI_ghash_insert(GHash *gh, void *key, void *val);
|
||||
void BLI_ghash_assign(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
|
||||
void *BLI_ghash_lookup(GHash *gh, const void *key);
|
||||
void **BLI_ghash_lookup_p(GHash *gh, const void *key);
|
||||
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
|
||||
|
@ -84,6 +84,69 @@ typedef struct GHash {
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* GHash API */
|
||||
|
||||
/* internal utility API */
|
||||
|
||||
BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key)
|
||||
{
|
||||
return gh->hashfp(key) % gh->nbuckets;
|
||||
}
|
||||
|
||||
BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key,
|
||||
const unsigned int hash)
|
||||
{
|
||||
Entry *e;
|
||||
|
||||
for (e = gh->buckets[hash]; e; e = e->next) {
|
||||
if (gh->cmpfp(key, e->key) == 0) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key)
|
||||
{
|
||||
const unsigned int hash = ghash_keyhash(gh, key);
|
||||
return ghash_lookup_entry_ex(gh, key, hash);
|
||||
}
|
||||
|
||||
static void ghash_insert_ex(GHash *gh, void *key, void *val,
|
||||
unsigned int hash)
|
||||
{
|
||||
Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
|
||||
|
||||
BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
|
||||
|
||||
e->next = gh->buckets[hash];
|
||||
e->key = key;
|
||||
e->val = val;
|
||||
gh->buckets[hash] = e;
|
||||
|
||||
if (UNLIKELY(++gh->nentries > gh->nbuckets / 2)) {
|
||||
Entry **old = gh->buckets;
|
||||
const unsigned nold = gh->nbuckets;
|
||||
unsigned int i;
|
||||
|
||||
gh->nbuckets = hashsizes[++gh->cursize];
|
||||
gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
|
||||
|
||||
for (i = 0; i < nold; i++) {
|
||||
Entry *e_next;
|
||||
for (e = old[i]; e; e = e_next) {
|
||||
e_next = e->next;
|
||||
hash = ghash_keyhash(gh, e->key);
|
||||
e->next = gh->buckets[hash];
|
||||
gh->buckets[hash] = e;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Public API */
|
||||
|
||||
GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
|
||||
{
|
||||
GHash *gh = MEM_mallocN(sizeof(*gh), info);
|
||||
@ -107,49 +170,31 @@ int BLI_ghash_size(GHash *gh)
|
||||
|
||||
void BLI_ghash_insert(GHash *gh, void *key, void *val)
|
||||
{
|
||||
unsigned int hash = gh->hashfp(key) % gh->nbuckets;
|
||||
Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
|
||||
|
||||
BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
|
||||
|
||||
e->next = gh->buckets[hash];
|
||||
e->key = key;
|
||||
e->val = val;
|
||||
gh->buckets[hash] = e;
|
||||
|
||||
if (UNLIKELY(++gh->nentries > gh->nbuckets / 2)) {
|
||||
Entry **old = gh->buckets;
|
||||
const unsigned nold = gh->nbuckets;
|
||||
unsigned int i;
|
||||
|
||||
gh->nbuckets = hashsizes[++gh->cursize];
|
||||
gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
|
||||
|
||||
for (i = 0; i < nold; i++) {
|
||||
Entry *e_next;
|
||||
for (e = old[i]; e; e = e_next) {
|
||||
e_next = e->next;
|
||||
hash = gh->hashfp(e->key) % gh->nbuckets;
|
||||
e->next = gh->buckets[hash];
|
||||
gh->buckets[hash] = e;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(old);
|
||||
}
|
||||
const unsigned int hash = ghash_keyhash(gh, key);
|
||||
ghash_insert_ex(gh, key, val, hash);
|
||||
}
|
||||
|
||||
BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key)
|
||||
/**
|
||||
* Assign a new value to a key that may already be in ghash.
|
||||
* Avoids #BLI_ghash_remove, #BLI_ghash_insert calls (double lookups)
|
||||
*
|
||||
* \note We may want to have 'BLI_ghash_assign_ex' function that takes
|
||||
* GHashKeyFreeFP & GHashValFreeFP args. for now aren't needed.
|
||||
*/
|
||||
void BLI_ghash_assign(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
|
||||
{
|
||||
const unsigned int hash = gh->hashfp(key) % gh->nbuckets;
|
||||
Entry *e;
|
||||
const unsigned int hash = ghash_keyhash(gh, key);
|
||||
Entry *e = ghash_lookup_entry_ex(gh, key, hash);
|
||||
if (e) {
|
||||
if (keyfreefp) keyfreefp(e->key);
|
||||
if (valfreefp) valfreefp(e->val);
|
||||
|
||||
for (e = gh->buckets[hash]; e; e = e->next) {
|
||||
if (gh->cmpfp(key, e->key) == 0) {
|
||||
return e;
|
||||
}
|
||||
e->key = key;
|
||||
e->val = val;
|
||||
}
|
||||
else {
|
||||
ghash_insert_ex(gh, key, val, hash);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *BLI_ghash_lookup(GHash *gh, const void *key)
|
||||
@ -166,7 +211,7 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key)
|
||||
|
||||
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
|
||||
{
|
||||
unsigned int hash = gh->hashfp(key) % gh->nbuckets;
|
||||
const unsigned int hash = ghash_keyhash(gh, key);
|
||||
Entry *e;
|
||||
Entry *p = NULL;
|
||||
|
||||
@ -196,7 +241,7 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr
|
||||
* no free value argument since it will be returned */
|
||||
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
|
||||
{
|
||||
unsigned int hash = gh->hashfp(key) % gh->nbuckets;
|
||||
const unsigned int hash = ghash_keyhash(gh, key);
|
||||
Entry *e;
|
||||
Entry *p = NULL;
|
||||
|
||||
|
@ -55,8 +55,6 @@ static const unsigned int _ehash_hashsizes[] = {
|
||||
268435459
|
||||
};
|
||||
|
||||
#define EDGE_HASH(v0, v1) ((v0 * 39) ^ (v1 * 31))
|
||||
|
||||
/* ensure v0 is smaller */
|
||||
#define EDGE_ORD(v0, v1) \
|
||||
if (v0 > v1) { \
|
||||
@ -84,37 +82,48 @@ struct EdgeHash {
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* EdgeHash API */
|
||||
|
||||
EdgeHash *BLI_edgehash_new(void)
|
||||
{
|
||||
EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash");
|
||||
eh->cursize = 0;
|
||||
eh->nentries = 0;
|
||||
eh->nbuckets = _ehash_hashsizes[eh->cursize];
|
||||
|
||||
eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2");
|
||||
eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, BLI_MEMPOOL_SYSMALLOC);
|
||||
/* internal utility API */
|
||||
|
||||
return eh;
|
||||
#define EDGE_HASH(v0, v1) ((v0 * 39) ^ (v1 * 31))
|
||||
|
||||
BLI_INLINE unsigned int edgehash_keyhash(EdgeHash *eh, unsigned int v0, unsigned int v1)
|
||||
{
|
||||
BLI_assert(v0 < v1);
|
||||
return EDGE_HASH(v0, v1) % eh->nbuckets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert edge (\a v0, \a v1) into hash with given value, does
|
||||
* not check for duplicates.
|
||||
*/
|
||||
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
|
||||
BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, unsigned int v1,
|
||||
const unsigned int hash)
|
||||
{
|
||||
EdgeEntry *e;
|
||||
BLI_assert(v0 < v1);
|
||||
for (e = eh->buckets[hash]; e; e = e->next) {
|
||||
if (v0 == e->v0 && v1 == e->v1) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsigned int v1)
|
||||
{
|
||||
unsigned int hash;
|
||||
EDGE_ORD(v0, v1); /* ensure v0 is smaller */
|
||||
hash = edgehash_keyhash(eh, v0, v1);
|
||||
return edgehash_lookup_entry_ex(eh, v0, v1, hash);
|
||||
}
|
||||
|
||||
static void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val,
|
||||
unsigned int hash)
|
||||
{
|
||||
EdgeEntry *e = BLI_mempool_alloc(eh->epool);
|
||||
|
||||
BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0));
|
||||
|
||||
/* this helps to track down errors with bad edge data */
|
||||
BLI_assert(v0 < v1);
|
||||
BLI_assert(v0 != v1);
|
||||
|
||||
EDGE_ORD(v0, v1); /* ensure v0 is smaller */
|
||||
|
||||
hash = EDGE_HASH(v0, v1) % eh->nbuckets;
|
||||
|
||||
e->next = eh->buckets[hash];
|
||||
e->v0 = v0;
|
||||
e->v1 = v1;
|
||||
@ -133,7 +142,7 @@ void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *v
|
||||
EdgeEntry *e_next;
|
||||
for (e = old[i]; e; e = e_next) {
|
||||
e_next = e->next;
|
||||
hash = EDGE_HASH(e->v0, e->v1) % eh->nbuckets;
|
||||
hash = edgehash_keyhash(eh, e->v0, e->v1);
|
||||
e->next = eh->buckets[hash];
|
||||
eh->buckets[hash] = e;
|
||||
}
|
||||
@ -143,20 +152,54 @@ void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *v
|
||||
}
|
||||
}
|
||||
|
||||
BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsigned int v1)
|
||||
#undef EDGE_HASH
|
||||
|
||||
|
||||
/* Public API */
|
||||
|
||||
EdgeHash *BLI_edgehash_new(void)
|
||||
{
|
||||
EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash");
|
||||
eh->cursize = 0;
|
||||
eh->nentries = 0;
|
||||
eh->nbuckets = _ehash_hashsizes[eh->cursize];
|
||||
|
||||
eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2");
|
||||
eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, BLI_MEMPOOL_SYSMALLOC);
|
||||
|
||||
return eh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert edge (\a v0, \a v1) into hash with given value, does
|
||||
* not check for duplicates.
|
||||
*/
|
||||
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
|
||||
{
|
||||
unsigned int hash;
|
||||
EDGE_ORD(v0, v1); /* ensure v0 is smaller */
|
||||
hash = edgehash_keyhash(eh, v0, v1);
|
||||
edgehash_insert_ex(eh, v0, v1, val, hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a new value to a key that may already be in edgehash.
|
||||
*/
|
||||
void BLI_edgehash_assign(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
|
||||
{
|
||||
unsigned int hash;
|
||||
EdgeEntry *e;
|
||||
|
||||
EDGE_ORD(v0, v1); /* ensure v0 is smaller */
|
||||
hash = edgehash_keyhash(eh, v0, v1);
|
||||
|
||||
hash = EDGE_HASH(v0, v1) % eh->nbuckets;
|
||||
for (e = eh->buckets[hash]; e; e = e->next) {
|
||||
if (v0 == e->v0 && v1 == e->v1) {
|
||||
return e;
|
||||
}
|
||||
e = edgehash_lookup_entry_ex(eh, v0, v1, hash);
|
||||
if (e) {
|
||||
e->val = val;
|
||||
}
|
||||
else {
|
||||
edgehash_insert_ex(eh, v0, v1, val, hash);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,10 +117,8 @@ static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id)
|
||||
{
|
||||
void *vid = SET_INT_IN_POINTER(id);
|
||||
|
||||
BLI_ghash_remove(log->id_to_elem, vid, NULL, NULL);
|
||||
BLI_ghash_insert(log->id_to_elem, vid, v);
|
||||
BLI_ghash_remove(log->elem_to_id, v, NULL, NULL);
|
||||
BLI_ghash_insert(log->elem_to_id, v, vid);
|
||||
BLI_ghash_assign(log->id_to_elem, vid, v, NULL, NULL);
|
||||
BLI_ghash_assign(log->elem_to_id, v, vid, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Get a vertex from its unique ID */
|
||||
@ -142,11 +140,9 @@ static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f)
|
||||
static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id)
|
||||
{
|
||||
void *fid = SET_INT_IN_POINTER(id);
|
||||
|
||||
BLI_ghash_remove(log->id_to_elem, fid, NULL, NULL);
|
||||
BLI_ghash_insert(log->id_to_elem, fid, f);
|
||||
BLI_ghash_remove(log->elem_to_id, f, NULL, NULL);
|
||||
BLI_ghash_insert(log->elem_to_id, f, fid);
|
||||
|
||||
BLI_ghash_assign(log->id_to_elem, fid, f, NULL, NULL);
|
||||
BLI_ghash_assign(log->elem_to_id, f, fid, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Get a face from its unique ID */
|
||||
|
@ -3207,9 +3207,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA
|
||||
* in the first place */
|
||||
if (prop->identifier) {
|
||||
if (cont->prophash) {
|
||||
BLI_ghash_remove(cont->prophash, (void *)prop->identifier, NULL, NULL);
|
||||
prop->identifier = BLI_strdup(prop->identifier);
|
||||
BLI_ghash_insert(cont->prophash, (void *)prop->identifier, prop);
|
||||
BLI_ghash_assign(cont->prophash, (void *)prop->identifier, prop, NULL, NULL);
|
||||
}
|
||||
else {
|
||||
prop->identifier = BLI_strdup(prop->identifier);
|
||||
|
Loading…
Reference in New Issue
Block a user