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.
|
||||
attrib->ref();
|
||||
}
|
||||
si = _attribs->store(attrib, Empty());
|
||||
si = _attribs->store(attrib, nullptr);
|
||||
|
||||
// Save the index and return the input attrib.
|
||||
attrib->_saved_entry = si;
|
||||
|
@ -185,9 +185,7 @@ public:
|
||||
private:
|
||||
// This mutex protects _attribs.
|
||||
static LightReMutex *_attribs_lock;
|
||||
class Empty {
|
||||
};
|
||||
typedef SimpleHashMap<const RenderAttrib *, Empty, indirect_compare_to_hash<const RenderAttrib *> > Attribs;
|
||||
typedef SimpleHashMap<const RenderAttrib *, nullptr_t, indirect_compare_to_hash<const RenderAttrib *> > Attribs;
|
||||
static Attribs *_attribs;
|
||||
|
||||
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.
|
||||
nassertr(RenderAttrib::_attribs->find(default_attrib) == -1, 0);
|
||||
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.
|
||||
|
@ -1338,7 +1338,7 @@ return_unique(RenderState *state) {
|
||||
// deleted while it's in it.
|
||||
state->cache_ref();
|
||||
}
|
||||
si = _states->store(state, Empty());
|
||||
si = _states->store(state, nullptr);
|
||||
|
||||
// Save the index and return the input state.
|
||||
state->_saved_entry = si;
|
||||
@ -1865,7 +1865,7 @@ init_states() {
|
||||
// is declared globally, and lives forever.
|
||||
RenderState *state = new RenderState;
|
||||
state->local_object();
|
||||
state->_saved_entry = _states->store(state, Empty());
|
||||
state->_saved_entry = _states->store(state, nullptr);
|
||||
_empty_state = state;
|
||||
}
|
||||
|
||||
|
@ -227,9 +227,7 @@ private:
|
||||
// cache, which is encoded in _composition_cache and
|
||||
// _invert_composition_cache.
|
||||
static LightReMutex *_states_lock;
|
||||
class Empty {
|
||||
};
|
||||
typedef SimpleHashMap<const RenderState *, Empty, indirect_compare_to_hash<const RenderState *> > States;
|
||||
typedef SimpleHashMap<const RenderState *, nullptr_t, indirect_compare_to_hash<const RenderState *> > States;
|
||||
static States *_states;
|
||||
static const RenderState *_empty_state;
|
||||
|
||||
|
@ -1512,7 +1512,7 @@ return_unique(TransformState *state) {
|
||||
// deleted while it's in it.
|
||||
state->cache_ref();
|
||||
}
|
||||
si = _states->store(state, Empty());
|
||||
si = _states->store(state, nullptr);
|
||||
|
||||
// Save the index and return the input state.
|
||||
state->_saved_entry = si;
|
||||
|
@ -253,9 +253,7 @@ private:
|
||||
// cache, which is encoded in _composition_cache and
|
||||
// _invert_composition_cache.
|
||||
static LightReMutex *_states_lock;
|
||||
class Empty {
|
||||
};
|
||||
typedef SimpleHashMap<const TransformState *, Empty, indirect_equals_hash<const TransformState *> > States;
|
||||
typedef SimpleHashMap<const TransformState *, nullptr_t, indirect_equals_hash<const TransformState *> > States;
|
||||
static States *_states;
|
||||
static CPT(TransformState) _identity_state;
|
||||
static CPT(TransformState) _invalid_state;
|
||||
|
@ -128,7 +128,7 @@ store(const Key &key, const Value &data) {
|
||||
}
|
||||
if (is_element(index, key)) {
|
||||
// This element is already in the map; replace the data at that key.
|
||||
_table[index]._data = data;
|
||||
set_data(index, data);
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), index);
|
||||
#endif
|
||||
@ -151,7 +151,7 @@ store(const Key &key, const Value &data) {
|
||||
return index;
|
||||
}
|
||||
if (is_element(index, key)) {
|
||||
_table[index]._data = data;
|
||||
set_data(index, data);
|
||||
#ifdef _DEBUG
|
||||
nassertr(validate(), index);
|
||||
#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
|
||||
// of entries.
|
||||
_table[index]._key = move(_table[last]._key);
|
||||
_table[index]._data = move(_table[last]._data);
|
||||
_table[index] = move(_table[last]);
|
||||
index_array[(size_t)other_slot] = index;
|
||||
}
|
||||
|
||||
@ -311,8 +310,8 @@ get_key(size_t n) const {
|
||||
template<class Key, class Value, class Compare>
|
||||
INLINE const Value &SimpleHashMap<Key, Value, Compare>::
|
||||
get_data(size_t n) const {
|
||||
nassertr(n < _num_entries, _table[n]._data);
|
||||
return _table[n]._data;
|
||||
nassertr(n < _num_entries, _table[n].get_data());
|
||||
return _table[n].get_data();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,8 +322,8 @@ get_data(size_t n) const {
|
||||
template<class Key, class Value, class Compare>
|
||||
INLINE Value &SimpleHashMap<Key, Value, Compare>::
|
||||
modify_data(size_t n) {
|
||||
nassertr(n < _num_entries, _table[n]._data);
|
||||
return _table[n]._data;
|
||||
nassertr(n < _num_entries, _table[n].modify_data());
|
||||
return _table[n].modify_data();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,7 +335,19 @@ template<class Key, class Value, class Compare>
|
||||
INLINE void SimpleHashMap<Key, Value, Compare>::
|
||||
set_data(size_t n, const Value &data) {
|
||||
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 "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,
|
||||
* 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,
|
||||
* (e) permits removal and resizing during forward iteration, and
|
||||
* (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> > >
|
||||
class SimpleHashMap {
|
||||
@ -55,6 +103,7 @@ public:
|
||||
INLINE const Value &get_data(size_t n) const;
|
||||
INLINE Value &modify_data(size_t n);
|
||||
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);
|
||||
|
||||
INLINE size_t get_num_entries() const;
|
||||
@ -67,8 +116,6 @@ public:
|
||||
INLINE bool consider_shrink_table();
|
||||
|
||||
private:
|
||||
class TableEntry;
|
||||
|
||||
INLINE size_t get_hash(const Key &key) const;
|
||||
INLINE size_t next_hash(size_t hash) const;
|
||||
|
||||
@ -82,23 +129,8 @@ private:
|
||||
INLINE bool consider_expand_table();
|
||||
void resize_table(size_t new_size);
|
||||
|
||||
class TableEntry {
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
typedef SimpleKeyValuePair<Key, Value> TableEntry;
|
||||
TableEntry *_table;
|
||||
DeletedBufferChain *_deleted_chain;
|
||||
size_t _table_size;
|
||||
|
Loading…
x
Reference in New Issue
Block a user