h_find now via hash multimap instead of linear search (it's called often)
This was SVN commit r1015.
This commit is contained in:
parent
4934c7cbe2
commit
3d455fc05f
@ -186,7 +186,7 @@ static HDATA* h_data(const i32 idx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// note: VC7.1 optimizes the divisions to shift and mask.
|
||||
// note: VC7.1 optimizes the divides to shift and mask.
|
||||
|
||||
return &page[idx % hdata_per_page];
|
||||
}
|
||||
@ -346,6 +346,12 @@ static int free_idx(i32 idx)
|
||||
}
|
||||
|
||||
|
||||
// speed up h_find (called every h_alloc)
|
||||
// multimap, because we want to add handles of differing type but same key
|
||||
// (e.g. a VFile and Tex object for the same underlying filename hash key)
|
||||
typedef STL_HASH_MULTIMAP<uintptr_t, i32> Key2Idx;
|
||||
typedef Key2Idx::iterator It;
|
||||
static Key2Idx key2idx;
|
||||
|
||||
|
||||
int h_free(Handle& h, H_Type type)
|
||||
@ -378,6 +384,26 @@ int h_free(Handle& h, H_Type type)
|
||||
if(vtbl->dtor)
|
||||
vtbl->dtor(hd->user);
|
||||
|
||||
if(hd->key)
|
||||
{
|
||||
It it = key2idx.find(hd->key);
|
||||
// not found in mapping
|
||||
if(it == key2idx.end())
|
||||
debug_warn("h_free: not in key2idx");
|
||||
It end = key2idx.upper_bound(hd->key);
|
||||
for(; it != end; ++it)
|
||||
{
|
||||
i32 idx = it->second;
|
||||
HDATA* hd2 = h_data(idx);
|
||||
// found match
|
||||
if(hd2 && hd2->type == type && hd2->key == hd->key)
|
||||
{
|
||||
key2idx.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free((void*)hd->fn);
|
||||
|
||||
memset(hd, 0, sizeof(HDATA));
|
||||
@ -444,13 +470,11 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
|
||||
|
||||
//debug_out("alloc %s %s\n", type->name, fn);
|
||||
|
||||
// disable caching if no key, because it would never be found
|
||||
// no key => can never be found. disallow caching
|
||||
if(!key)
|
||||
flags |= RES_NO_CACHE; // changes scope to RES_TEMP
|
||||
|
||||
const uint scope = flags & RES_SCOPE_MASK;
|
||||
|
||||
if(key)
|
||||
// check if already loaded (cached)
|
||||
else
|
||||
{
|
||||
// object already loaded?
|
||||
h = h_find(type, key);
|
||||
@ -480,6 +504,8 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
|
||||
CHECK_ERR(alloc_idx(idx, hd));
|
||||
skip_alloc:
|
||||
|
||||
const uint scope = flags & RES_SCOPE_MASK;
|
||||
|
||||
// generate next tag value.
|
||||
// don't want to do this before the add-reference exit,
|
||||
// so as not to waste tags for often allocated handles.
|
||||
@ -505,7 +531,8 @@ skip_alloc:
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
if(key)
|
||||
key2idx.insert(std::make_pair(key, idx));
|
||||
|
||||
// one-time init
|
||||
hd->tag = tag;
|
||||
@ -636,21 +663,31 @@ int h_reload(const char* fn)
|
||||
}
|
||||
|
||||
|
||||
// TODO: more efficient search; currently linear
|
||||
Handle h_find(H_Type type, uintptr_t key)
|
||||
{
|
||||
for(i32 i = 0; i < last_in_use; i++)
|
||||
It it = key2idx.find(key);
|
||||
// not found in mapping
|
||||
if(it == key2idx.end())
|
||||
return -1;
|
||||
It end = key2idx.upper_bound(key);
|
||||
for(; it != end; ++it)
|
||||
{
|
||||
HDATA* hd = h_data(i);
|
||||
if(hd)
|
||||
if(hd->type == type && hd->key == key)
|
||||
return handle(i, hd->tag);
|
||||
i32 idx = it->second;
|
||||
HDATA* hd = h_data(idx);
|
||||
// found match
|
||||
if(hd && hd->type == type && hd->key == key)
|
||||
return handle(idx, hd->tag);
|
||||
}
|
||||
|
||||
// key is in the mapping, but it's of the wrong type.
|
||||
// this happens when called by h_alloc to check if
|
||||
// e.g. a Tex object already exists; at that time,
|
||||
// only the corresponding VFile exists.
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int res_cur_scope;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user