mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
More efficiently store SimpleHashMap with empty values
This commit is contained in:
parent
dee8d83998
commit
8078fa2b38
@ -389,7 +389,7 @@ return_unique(RenderAttrib *attrib) {
|
|||||||
// deleted while it's in it.
|
// deleted while it's in it.
|
||||||
attrib->ref();
|
attrib->ref();
|
||||||
}
|
}
|
||||||
si = _attribs->store(attrib, Empty());
|
si = _attribs->store(attrib, nullptr);
|
||||||
|
|
||||||
// Save the index and return the input attrib.
|
// Save the index and return the input attrib.
|
||||||
attrib->_saved_entry = si;
|
attrib->_saved_entry = si;
|
||||||
|
@ -185,9 +185,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// This mutex protects _attribs.
|
// This mutex protects _attribs.
|
||||||
static LightReMutex *_attribs_lock;
|
static LightReMutex *_attribs_lock;
|
||||||
class Empty {
|
typedef SimpleHashMap<const RenderAttrib *, nullptr_t, indirect_compare_to_hash<const RenderAttrib *> > Attribs;
|
||||||
};
|
|
||||||
typedef SimpleHashMap<const RenderAttrib *, Empty, indirect_compare_to_hash<const RenderAttrib *> > Attribs;
|
|
||||||
static Attribs *_attribs;
|
static Attribs *_attribs;
|
||||||
|
|
||||||
int _saved_entry;
|
int _saved_entry;
|
||||||
|
@ -93,7 +93,7 @@ register_slot(TypeHandle type_handle, int sort, RenderAttrib *default_attrib) {
|
|||||||
// If this attribute was already registered, something odd is going on.
|
// If this attribute was already registered, something odd is going on.
|
||||||
nassertr(RenderAttrib::_attribs->find(default_attrib) == -1, 0);
|
nassertr(RenderAttrib::_attribs->find(default_attrib) == -1, 0);
|
||||||
default_attrib->_saved_entry =
|
default_attrib->_saved_entry =
|
||||||
RenderAttrib::_attribs->store(default_attrib, RenderAttrib::Empty());
|
RenderAttrib::_attribs->store(default_attrib, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// It effectively lives forever. Might as well make it official.
|
// It effectively lives forever. Might as well make it official.
|
||||||
|
@ -1338,7 +1338,7 @@ return_unique(RenderState *state) {
|
|||||||
// deleted while it's in it.
|
// deleted while it's in it.
|
||||||
state->cache_ref();
|
state->cache_ref();
|
||||||
}
|
}
|
||||||
si = _states->store(state, Empty());
|
si = _states->store(state, nullptr);
|
||||||
|
|
||||||
// Save the index and return the input state.
|
// Save the index and return the input state.
|
||||||
state->_saved_entry = si;
|
state->_saved_entry = si;
|
||||||
@ -1865,7 +1865,7 @@ init_states() {
|
|||||||
// is declared globally, and lives forever.
|
// is declared globally, and lives forever.
|
||||||
RenderState *state = new RenderState;
|
RenderState *state = new RenderState;
|
||||||
state->local_object();
|
state->local_object();
|
||||||
state->_saved_entry = _states->store(state, Empty());
|
state->_saved_entry = _states->store(state, nullptr);
|
||||||
_empty_state = state;
|
_empty_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,9 +227,7 @@ private:
|
|||||||
// cache, which is encoded in _composition_cache and
|
// cache, which is encoded in _composition_cache and
|
||||||
// _invert_composition_cache.
|
// _invert_composition_cache.
|
||||||
static LightReMutex *_states_lock;
|
static LightReMutex *_states_lock;
|
||||||
class Empty {
|
typedef SimpleHashMap<const RenderState *, nullptr_t, indirect_compare_to_hash<const RenderState *> > States;
|
||||||
};
|
|
||||||
typedef SimpleHashMap<const RenderState *, Empty, indirect_compare_to_hash<const RenderState *> > States;
|
|
||||||
static States *_states;
|
static States *_states;
|
||||||
static const RenderState *_empty_state;
|
static const RenderState *_empty_state;
|
||||||
|
|
||||||
|
@ -1512,7 +1512,7 @@ return_unique(TransformState *state) {
|
|||||||
// deleted while it's in it.
|
// deleted while it's in it.
|
||||||
state->cache_ref();
|
state->cache_ref();
|
||||||
}
|
}
|
||||||
si = _states->store(state, Empty());
|
si = _states->store(state, nullptr);
|
||||||
|
|
||||||
// Save the index and return the input state.
|
// Save the index and return the input state.
|
||||||
state->_saved_entry = si;
|
state->_saved_entry = si;
|
||||||
|
@ -253,9 +253,7 @@ private:
|
|||||||
// cache, which is encoded in _composition_cache and
|
// cache, which is encoded in _composition_cache and
|
||||||
// _invert_composition_cache.
|
// _invert_composition_cache.
|
||||||
static LightReMutex *_states_lock;
|
static LightReMutex *_states_lock;
|
||||||
class Empty {
|
typedef SimpleHashMap<const TransformState *, nullptr_t, indirect_equals_hash<const TransformState *> > States;
|
||||||
};
|
|
||||||
typedef SimpleHashMap<const TransformState *, Empty, indirect_equals_hash<const TransformState *> > States;
|
|
||||||
static States *_states;
|
static States *_states;
|
||||||
static CPT(TransformState) _identity_state;
|
static CPT(TransformState) _identity_state;
|
||||||
static CPT(TransformState) _invalid_state;
|
static CPT(TransformState) _invalid_state;
|
||||||
|
@ -128,7 +128,7 @@ store(const Key &key, const Value &data) {
|
|||||||
}
|
}
|
||||||
if (is_element(index, key)) {
|
if (is_element(index, key)) {
|
||||||
// This element is already in the map; replace the data at that key.
|
// This element is already in the map; replace the data at that key.
|
||||||
_table[index]._data = data;
|
set_data(index, data);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(validate(), index);
|
nassertr(validate(), index);
|
||||||
#endif
|
#endif
|
||||||
@ -151,7 +151,7 @@ store(const Key &key, const Value &data) {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
if (is_element(index, key)) {
|
if (is_element(index, key)) {
|
||||||
_table[index]._data = data;
|
set_data(index, data);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(validate(), index);
|
nassertr(validate(), index);
|
||||||
#endif
|
#endif
|
||||||
@ -200,8 +200,7 @@ remove(const Key &key) {
|
|||||||
|
|
||||||
// Swap it with the last one, so that we don't get any gaps in the table
|
// Swap it with the last one, so that we don't get any gaps in the table
|
||||||
// of entries.
|
// of entries.
|
||||||
_table[index]._key = move(_table[last]._key);
|
_table[index] = move(_table[last]);
|
||||||
_table[index]._data = move(_table[last]._data);
|
|
||||||
index_array[(size_t)other_slot] = index;
|
index_array[(size_t)other_slot] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,8 +310,8 @@ get_key(size_t n) const {
|
|||||||
template<class Key, class Value, class Compare>
|
template<class Key, class Value, class Compare>
|
||||||
INLINE const Value &SimpleHashMap<Key, Value, Compare>::
|
INLINE const Value &SimpleHashMap<Key, Value, Compare>::
|
||||||
get_data(size_t n) const {
|
get_data(size_t n) const {
|
||||||
nassertr(n < _num_entries, _table[n]._data);
|
nassertr(n < _num_entries, _table[n].get_data());
|
||||||
return _table[n]._data;
|
return _table[n].get_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,8 +322,8 @@ get_data(size_t n) const {
|
|||||||
template<class Key, class Value, class Compare>
|
template<class Key, class Value, class Compare>
|
||||||
INLINE Value &SimpleHashMap<Key, Value, Compare>::
|
INLINE Value &SimpleHashMap<Key, Value, Compare>::
|
||||||
modify_data(size_t n) {
|
modify_data(size_t n) {
|
||||||
nassertr(n < _num_entries, _table[n]._data);
|
nassertr(n < _num_entries, _table[n].modify_data());
|
||||||
return _table[n]._data;
|
return _table[n].modify_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,7 +335,19 @@ template<class Key, class Value, class Compare>
|
|||||||
INLINE void SimpleHashMap<Key, Value, Compare>::
|
INLINE void SimpleHashMap<Key, Value, Compare>::
|
||||||
set_data(size_t n, const Value &data) {
|
set_data(size_t n, const Value &data) {
|
||||||
nassertv(n < _num_entries);
|
nassertv(n < _num_entries);
|
||||||
_table[n]._data = data;
|
_table[n].set_data(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the data for the nth entry of the table.
|
||||||
|
*
|
||||||
|
* @param n should be in the range 0 <= n < size().
|
||||||
|
*/
|
||||||
|
template<class Key, class Value, class Compare>
|
||||||
|
INLINE void SimpleHashMap<Key, Value, Compare>::
|
||||||
|
set_data(size_t n, Value &&data) {
|
||||||
|
nassertv(n < _num_entries);
|
||||||
|
_table[n].set_data(move(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,52 @@
|
|||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
#include "config_util.h"
|
#include "config_util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry in the SimpleHashMap.
|
||||||
|
*/
|
||||||
|
template<class Key, class Value>
|
||||||
|
class SimpleKeyValuePair {
|
||||||
|
public:
|
||||||
|
INLINE SimpleKeyValuePair(const Key &key, const Value &data) :
|
||||||
|
_key(key),
|
||||||
|
_data(data) {}
|
||||||
|
|
||||||
|
Key _key;
|
||||||
|
|
||||||
|
ALWAYS_INLINE const Value &get_data() const {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE Value &modify_data() {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE void set_data(const Value &data) {
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE void set_data(Value &&data) {
|
||||||
|
_data = move(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Value _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialisation of SimpleKeyValuePair to not waste memory for nullptr_t
|
||||||
|
* values. This allows effectively using SimpleHashMap as a set.
|
||||||
|
*/
|
||||||
|
template<class Key>
|
||||||
|
class SimpleKeyValuePair<Key, nullptr_t> {
|
||||||
|
public:
|
||||||
|
INLINE SimpleKeyValuePair(const Key &key, nullptr_t data) :
|
||||||
|
_key(key) {}
|
||||||
|
|
||||||
|
Key _key;
|
||||||
|
|
||||||
|
ALWAYS_INLINE_CONSTEXPR static nullptr_t get_data() { return nullptr; }
|
||||||
|
ALWAYS_INLINE_CONSTEXPR static nullptr_t modify_data() { return nullptr; }
|
||||||
|
ALWAYS_INLINE static void set_data(nullptr_t) {}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This template class implements an unordered map of keys to data,
|
* This template class implements an unordered map of keys to data,
|
||||||
* implemented as a hashtable. It is similar to STL's hash_map, but
|
* implemented as a hashtable. It is similar to STL's hash_map, but
|
||||||
@ -28,6 +74,8 @@
|
|||||||
* (d) it allows for efficient iteration over the entries,
|
* (d) it allows for efficient iteration over the entries,
|
||||||
* (e) permits removal and resizing during forward iteration, and
|
* (e) permits removal and resizing during forward iteration, and
|
||||||
* (f) it has a constexpr constructor.
|
* (f) it has a constexpr constructor.
|
||||||
|
*
|
||||||
|
* It can also be used as a set, by using nullptr_t as Value typename.
|
||||||
*/
|
*/
|
||||||
template<class Key, class Value, class Compare = method_hash<Key, less<Key> > >
|
template<class Key, class Value, class Compare = method_hash<Key, less<Key> > >
|
||||||
class SimpleHashMap {
|
class SimpleHashMap {
|
||||||
@ -55,6 +103,7 @@ public:
|
|||||||
INLINE const Value &get_data(size_t n) const;
|
INLINE const Value &get_data(size_t n) const;
|
||||||
INLINE Value &modify_data(size_t n);
|
INLINE Value &modify_data(size_t n);
|
||||||
INLINE void set_data(size_t n, const Value &data);
|
INLINE void set_data(size_t n, const Value &data);
|
||||||
|
INLINE void set_data(size_t n, Value &&data);
|
||||||
void remove_element(size_t n);
|
void remove_element(size_t n);
|
||||||
|
|
||||||
INLINE size_t get_num_entries() const;
|
INLINE size_t get_num_entries() const;
|
||||||
@ -67,8 +116,6 @@ public:
|
|||||||
INLINE bool consider_shrink_table();
|
INLINE bool consider_shrink_table();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class TableEntry;
|
|
||||||
|
|
||||||
INLINE size_t get_hash(const Key &key) const;
|
INLINE size_t get_hash(const Key &key) const;
|
||||||
INLINE size_t next_hash(size_t hash) const;
|
INLINE size_t next_hash(size_t hash) const;
|
||||||
|
|
||||||
@ -82,23 +129,8 @@ private:
|
|||||||
INLINE bool consider_expand_table();
|
INLINE bool consider_expand_table();
|
||||||
void resize_table(size_t new_size);
|
void resize_table(size_t new_size);
|
||||||
|
|
||||||
class TableEntry {
|
public:
|
||||||
public:
|
typedef SimpleKeyValuePair<Key, Value> TableEntry;
|
||||||
INLINE TableEntry(const Key &key, const Value &data) :
|
|
||||||
_key(key),
|
|
||||||
_data(data) {}
|
|
||||||
INLINE TableEntry(const TableEntry ©) :
|
|
||||||
_key(copy._key),
|
|
||||||
_data(copy._data) {}
|
|
||||||
#ifdef USE_MOVE_SEMANTICS
|
|
||||||
INLINE TableEntry(TableEntry &&from) NOEXCEPT :
|
|
||||||
_key(move(from._key)),
|
|
||||||
_data(move(from._data)) {}
|
|
||||||
#endif
|
|
||||||
Key _key;
|
|
||||||
Value _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
TableEntry *_table;
|
TableEntry *_table;
|
||||||
DeletedBufferChain *_deleted_chain;
|
DeletedBufferChain *_deleted_chain;
|
||||||
size_t _table_size;
|
size_t _table_size;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user