TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
G3D::Table< Key, Value, HashFunc, EqualsFunc > Class Template Reference

#include <Table.h>

Classes

class  Entry
 
class  Iterator
 
class  Node
 

Public Member Functions

 Table ()
 
void clearAndSetMemoryManager (const MemoryManager::Ref &m)
 
void setSizeHint (size_t n)
 
virtual ~Table ()
 
 Table (const ThisType &h)
 
Tableoperator= (const ThisType &h)
 
size_t debugGetDeepestBucketSize () const
 
float debugGetAverageBucketSize () const
 
double debugGetLoad () const
 
size_t debugGetNumBuckets () const
 
Iterator begin () const
 
const Iterator end () const
 
void clear ()
 
size_t size () const
 
void set (const Key &key, const Value &value)
 
bool getRemove (const Key &key, Key &removedKey, Value &removedValue)
 
bool remove (const Key &key)
 
const Key * getKeyPointer (const Key &key) const
 
Valueget (const Key &key) const
 
ValuegetPointer (const Key &key) const
 
bool get (const Key &key, Value &val) const
 
EntrygetCreateEntry (const Key &key, bool &created)
 
EntrygetCreateEntry (const Key &key)
 
ValuegetCreate (const Key &key)
 
ValuegetCreate (const Key &key, bool &created)
 
bool containsKey (const Key &key) const
 
Valueoperator[] (const Key &key) const
 
Array< Key > getKeys () const
 
void getKeys (Array< Key > &keyArray) const
 
void getValues (Array< Value > &valueArray) const
 
void deleteKeys ()
 
void deleteValues ()
 
template<class H , class E >
bool operator== (const Table< Key, Value, H, E > &other) const
 
template<class H , class E >
bool operator!= (const Table< Key, Value, H, E > &other) const
 
void debugPrintStatus ()
 

Private Types

typedef Table< Key, Value,
HashFunc, EqualsFunc > 
ThisType
 

Private Member Functions

void checkIntegrity () const
 
void * alloc (size_t s) const
 
void free (void *p) const
 
void resize (size_t newSize)
 
void copyFrom (const ThisType &h)
 
void freeMemory ()
 
bool remove (const Key &key, Key &removedKey, Value &removedValue, bool updateRemoved)
 
EntrygetEntryPointer (const Key &key) const
 

Private Attributes

size_t m_size
 
Node ** m_bucket
 
size_t m_numBuckets
 
MemoryManager::Ref m_memoryManager
 

Detailed Description

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
class G3D::Table< Key, Value, HashFunc, EqualsFunc >

An unordered data structure mapping keys to values.

There are two ways of definining custom hash functions (G3D provides built-in ones for most classes):

class Foo {
public:
    std::string     name;
    int             index;
    static size_t hashCode(const Foo& key) {
         return HashTrait<std::string>::hashCode(key.name) + key.index;
    }
 };
 template<> struct HashTrait<class Foo> {
      static size_t hashCode(const Foo& key) { return HashTrait<std::string>::hashCode(key.name) + key.index; }
 };
 // Use Foo::hashCode
 Table<Foo, std::string, Foo> fooTable1;
 // Use HashTrait<Foo>
 Table<Foo, std::string>      fooTable2;
 

Key must be a pointer, an int, a std::string or provide overloads for:

   template<> struct HashTrait<class Key> {
       static size_t hashCode(const Key& key) { return reinterpret_cast<size_t>( ... ); }
   }; 
 

and one of

   template<> struct EqualsTrait<class Key>{
        static bool equals(const Key& a, const Key& b) { return ... ; }
   };
   bool operator==(const Key&, const Key&);
 

G3D pre-defines HashTrait specializations for common types (like int and std::string). If you use a Table with a different type you must write those functions yourself. For example, an enum would use:

   template<> struct HashTrait<MyEnum> {
       static size_t hashCode(const MyEnum& key) const { return reinterpret_cast<size_t>( key ); }
   };
 

And rely on the default enum operator==.

Periodically check that debugGetLoad() is low (> 0.1). When it gets near 1.0 your hash function is badly designed and maps too many inputs to the same output.

Member Typedef Documentation

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
typedef Table<Key, Value, HashFunc, EqualsFunc> G3D::Table< Key, Value, HashFunc, EqualsFunc >::ThisType
private

Constructor & Destructor Documentation

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
G3D::Table< Key, Value, HashFunc, EqualsFunc >::Table ( )
inline

Creates an empty hash table using the default MemoryManager.

300  : m_bucket(NULL) {
302  m_numBuckets = 0;
303  m_size = 0;
304  m_bucket = NULL;
305  checkIntegrity();
306  }
static MemoryManager::Ref create()
Definition: MemoryManager.cpp:35
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
void checkIntegrity() const
Definition: Table.h:169
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
virtual G3D::Table< Key, Value, HashFunc, EqualsFunc >::~Table ( )
inlinevirtual

Destroys all of the memory allocated by the table, but does not call delete on keys or values if they are pointers. If you want to deallocate things that the table points at, use getKeys() and Array::deleteAll() to delete them.

331  {
332  freeMemory();
333  }
void freeMemory()
Definition: Table.h:277
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
G3D::Table< Key, Value, HashFunc, EqualsFunc >::Table ( const ThisType h)
inline

Uses the default memory manager

336  {
338  m_numBuckets = 0;
339  m_size = 0;
340  m_bucket = NULL;
341  this->copyFrom(h);
342  checkIntegrity();
343  }
static MemoryManager::Ref create()
Definition: MemoryManager.cpp:35
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
void checkIntegrity() const
Definition: Table.h:169
void copyFrom(const ThisType &h)
Definition: Table.h:252
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197

Member Function Documentation

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void* G3D::Table< Key, Value, HashFunc, EqualsFunc >::alloc ( size_t  s) const
inlineprivate
201  {
202  return m_memoryManager->alloc(s);
203  }
MemoryManager::Ref m_memoryManager
Definition: Table.h:199

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Iterator G3D::Table< Key, Value, HashFunc, EqualsFunc >::begin ( ) const
inline

C++ STL style iterator method. Returns the first Entry, which contains a key and value. Use preincrement (++entry) to get to the next element. Do not modify the table while iterating.

562  {
563  return Iterator(m_numBuckets, m_bucket);
564  }
Node ** m_bucket
Definition: Table.h:192
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::checkIntegrity ( ) const
inlineprivate
169  {
170 # ifdef G3D_DEBUG
172  for (size_t b = 0; b < m_numBuckets; ++b) {
173  Node* node = m_bucket[b];
174  debugAssert(node == NULL || isValidHeapPointer(node));
175  while (node != NULL) {
176  debugAssert(node == NULL || isValidHeapPointer(node));
177  node = node->next;
178  }
179  }
180 # endif
181  }
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
#define debugAssert(exp)
Definition: debugAssert.h:160
bool isValidHeapPointer(const void *x)
Definition: debug.h:38
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::clear ( )
inline

Removes all elements. Guaranteed to free all memory associated with the table.

578  {
579  freeMemory();
580  m_numBuckets = 0;
581  m_size = 0;
582  m_bucket = NULL;
583  }
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
void freeMemory()
Definition: Table.h:277
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::clearAndSetMemoryManager ( const MemoryManager::Ref m)
inline

Changes the internal memory manager to m

309  {
310  clear();
312  m_memoryManager = m;
313  }
void clear()
Definition: Table.h:578
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
#define debugAssert(exp)
Definition: debugAssert.h:160
MemoryManager::Ref m_memoryManager
Definition: Table.h:199

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::containsKey ( const Key &  key) const
inline

Returns true if key is in the table.

874  {
875  if (m_numBuckets == 0) {
876  return false;
877  }
878 
879  size_t code = HashFunc::hashCode(key);
880  size_t b = code % m_numBuckets;
881 
882  Node* node = m_bucket[b];
883 
884  while (node != NULL) {
885  if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
886  return true;
887  }
888  node = node->next;
889  }
890 
891  return false;
892  }
size_t hashCode() const
Definition: Vector2unorm16.h:76
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
Definition: inftrees.h:24
Node * next
Definition: Table.h:129
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::copyFrom ( const ThisType h)
inlineprivate
252  {
253  if (&h == this) {
254  return;
255  }
256 
258  m_size = h.m_size;
259  m_numBuckets = h.m_numBuckets;
260  m_bucket = (Node**)alloc(sizeof(Node*) * m_numBuckets);
261  // No need to NULL elements since we're about to overwrite them
262 
263  for (size_t b = 0; b < m_numBuckets; ++b) {
264  if (h.m_bucket[b] != NULL) {
265  m_bucket[b] = h.m_bucket[b]->clone(m_memoryManager);
266  } else {
267  m_bucket[b] = NULL;
268  }
269  }
270 
271  checkIntegrity();
272  }
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
void checkIntegrity() const
Definition: Table.h:169
#define debugAssert(exp)
Definition: debugAssert.h:160
void * alloc(size_t s) const
Definition: Table.h:201
Node * clone(MemoryManager::Ref &mm)
Definition: Table.h:164
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
float G3D::Table< Key, Value, HashFunc, EqualsFunc >::debugGetAverageBucketSize ( ) const
inline

Returns the average size of non-empty buckets.

382  {
383  uint64 num = 0;
384 
385  for (size_t b = 0; b < m_numBuckets; ++b) {
386  Node* node = m_bucket[b];
387  if (node != NULL) {
388  ++num;
389  }
390  }
391 
392  return (float)((double)size() / num);
393  }
size_t size() const
Definition: Table.h:589
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
uint64_t uint64
Definition: Define.h:149
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
size_t G3D::Table< Key, Value, HashFunc, EqualsFunc >::debugGetDeepestBucketSize ( ) const
inline

Returns the length of the deepest m_bucket.

360  {
361  size_t deepest = 0;
362 
363  for (size_t b = 0; b < m_numBuckets; ++b) {
364  size_t count = 0;
365  Node* node = m_bucket[b];
366  while (node != NULL) {
367  node = node->next;
368  ++count;
369  }
370 
371  if (count > deepest) {
372  deepest = count;
373  }
374  }
375 
376  return deepest;
377  }
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
Node * next
Definition: Table.h:129
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
double G3D::Table< Key, Value, HashFunc, EqualsFunc >::debugGetLoad ( ) const
inline

A small load (close to zero) means the hash table is acting very efficiently most of the time. A large load (close to 1) means the hash table is acting poorly– all operations will be very slow. A large load will result from a bad hash function that maps too many keys to the same code.

402  {
403  return (double)size() / m_numBuckets;
404  }
size_t size() const
Definition: Table.h:589
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
size_t G3D::Table< Key, Value, HashFunc, EqualsFunc >::debugGetNumBuckets ( ) const
inline

Returns the number of buckets.

409  {
410  return m_numBuckets;
411  }
size_t m_numBuckets
Definition: Table.h:197
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::debugPrintStatus ( )
inline
995  {
996  debugPrintf("Deepest bucket size = %d\n", (int)debugGetDeepestBucketSize());
997  debugPrintf("Average bucket size = %g\n", debugGetAverageBucketSize());
998  debugPrintf("Load factor = %g\n", debugGetLoad());
999  }
std::string __cdecl debugPrintf(const char *fmt...) G3D_CHECK_PRINTF_ARGS
Definition: debugAssert.cpp:355
float debugGetAverageBucketSize() const
Definition: Table.h:382
double debugGetLoad() const
Definition: Table.h:402
size_t debugGetDeepestBucketSize() const
Definition: Table.h:360
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::deleteKeys ( )
inline

Calls delete on all of the keys and then clears the table.

939  {
940  for (size_t i = 0; i < m_numBuckets; ++i) {
941  Node* node = m_bucket[i];
942  while (node != NULL) {
943  delete node->entry.key;
944  node->entry.key = NULL;
945  node = node->next;
946  }
947  }
948  clear();
949  }
void clear()
Definition: Table.h:578
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
Key key
Definition: Table.h:109
Entry entry
Definition: Table.h:127
size_t m_numBuckets
Definition: Table.h:197
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::deleteValues ( )
inline

Calls delete on all of the values. This is unsafe– do not call unless you know that each value appears at most once.

Does not clear the table, so you are left with a table of NULL pointers.

959  {
960  for (size_t i = 0; i < m_numBuckets; ++i) {
961  Node* node = m_bucket[i];
962  while (node != NULL) {
963  delete node->entry.value;
964  node->entry.value = NULL;
965  node = node->next;
966  }
967  }
968  }
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
Value value
Definition: Table.h:110
Entry entry
Definition: Table.h:127
size_t m_numBuckets
Definition: Table.h:197
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
const Iterator G3D::Table< Key, Value, HashFunc, EqualsFunc >::end ( ) const
inline

C++ STL style iterator method. Returns one after the last iterator element.

570  {
571  return Iterator();
572  }

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::free ( void *  p) const
inlineprivate
205  {
206  return m_memoryManager->free(p);
207  }
MemoryManager::Ref m_memoryManager
Definition: Table.h:199

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::freeMemory ( )
inlineprivate

Frees the heap structures for the nodes.

277  {
278  checkIntegrity();
279 
280  for (size_t b = 0; b < m_numBuckets; ++b) {
281  Node* node = m_bucket[b];
282  while (node != NULL) {
283  Node* next = node->next;
285  node = next;
286  }
287  m_bucket[b] = NULL;
288  }
289  free(m_bucket);
290  m_bucket = NULL;
291  m_numBuckets = 0;
292  m_size = 0;
293  }
static void destroy(Node *n, MemoryManager::Ref &mm)
Definition: Table.h:156
void free(void *p) const
Definition: Table.h:205
int next(int i, int n)
Definition: RecastContour.cpp:469
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
void checkIntegrity() const
Definition: Table.h:169
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Value& G3D::Table< Key, Value, HashFunc, EqualsFunc >::get ( const Key &  key) const
inline

Returns the value associated with key.

Deprecated:
Use get(key, val) or getPointer(key)
714  {
715  Entry* e = getEntryPointer(key);
716  debugAssertM(e != NULL, "Key not found");
717  return e->value;
718  }
arena_t NULL
Definition: jemalloc_internal.h:624
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
Entry
Definition: boss_headless_horseman.cpp:50
Entry * getEntryPointer(const Key &key) const
Definition: Table.h:676
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::get ( const Key &  key,
Value val 
) const
inline

If the key is present in the table, val is set to the associated value and returns true. If the key is not present, returns false.

757  {
758  Value* v = getPointer(key);
759  if (v != NULL) {
760  val = *v;
761  return true;
762  } else {
763  return false;
764  }
765  }
Value * getPointer(const Key &key) const
Definition: Table.h:731
arena_t NULL
Definition: jemalloc_internal.h:624
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Value& G3D::Table< Key, Value, HashFunc, EqualsFunc >::getCreate ( const Key &  key)
inline

Returns the current value that key maps to, creating it if necessary.

861  {
862  return getCreateEntry(key).value;
863  }
Entry & getCreateEntry(const Key &key, bool &created)
Definition: Table.h:772
Value value
Definition: Table.h:110

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Value& G3D::Table< Key, Value, HashFunc, EqualsFunc >::getCreate ( const Key &  key,
bool created 
)
inline
Parameters
createdTrue if the element was created.
866  {
867  return getCreateEntry(key, created).value;
868  }
Entry & getCreateEntry(const Key &key, bool &created)
Definition: Table.h:772
Value value
Definition: Table.h:110
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Entry& G3D::Table< Key, Value, HashFunc, EqualsFunc >::getCreateEntry ( const Key &  key,
bool created 
)
inline

Called by getCreate() and set()

Parameters
createdSet to true if the entry was created by this method.
772  {
773  created = false;
774 
775  if (m_numBuckets == 0) {
776  resize(10);
777  }
778 
779  size_t code = HashFunc::hashCode(key);
780  size_t b = code % m_numBuckets;
781 
782  // Go to the m_bucket
783  Node* n = m_bucket[b];
784 
785  // No m_bucket, so this must be the first
786  if (n == NULL) {
787  m_bucket[b] = Node::create(key, code, NULL, m_memoryManager);
788  ++m_size;
789  created = true;
790  //checkIntegrity();
791  return m_bucket[b]->entry;
792  }
793 
794  size_t bucketLength = 1;
795 
796  // Sometimes a bad hash code will cause all elements
797  // to collide. Detect this case and don't rehash when
798  // it occurs; nothing good will come from the rehashing.
799  bool allSameCode = true;
800 
801  // Try to find the node
802  do {
803  allSameCode = allSameCode && (code == n->hashCode);
804 
805  if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
806  // This is the a pre-existing node
807  //checkIntegrity();
808  return n->entry;
809  }
810 
811  n = n->next;
812  ++bucketLength;
813  } while (n != NULL);
814 
815  // Allow the load factor to rise as the table gets huge
816  const int bucketsPerElement =
817  (m_size > 50000) ? 3 :
818  ((m_size > 10000) ? 5 :
819  ((m_size > 5000) ? 10 : 15));
820 
821  const size_t maxBucketLength = 3;
822  // (Don't bother changing the size of the table if all entries
823  // have the same hashcode--they'll still collide)
824  if ((bucketLength > maxBucketLength) &&
825  ! allSameCode &&
826  (m_numBuckets < m_size * bucketsPerElement)) {
827 
828  // This m_bucket was really large; rehash if all elements
829  // don't have the same hashcode the number of buckets is
830  // reasonable.
831 
832  // Back off the scale factor as the number of buckets gets
833  // large
834  float f = 3.0f;
835  if (m_numBuckets > 1000000) {
836  f = 1.5f;
837  } else if (m_numBuckets > 100000) {
838  f = 2.0f;
839  }
840  int newSize = iMax((int)(m_numBuckets * f) + 1, (int)(m_size * f));
841  resize(newSize);
842  }
843 
844  // Not found; insert at the head.
845  b = code % m_numBuckets;
846  m_bucket[b] = Node::create(key, code, m_bucket[b], m_memoryManager);
847  ++m_size;
848  created = true;
849 
850  //checkIntegrity();
851  return m_bucket[b]->entry;
852  }
size_t hashCode() const
Definition: Vector2unorm16.h:76
static Node * create(const Key &k, const Value &v, size_t h, Node *n, MemoryManager::Ref &mm)
Definition: Table.h:146
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
void resize(size_t newSize)
Definition: Table.h:212
Definition: inftrees.h:24
Entry entry
Definition: Table.h:127
int iMax(int x, int y)
Definition: g3dmath.h:759
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Entry& G3D::Table< Key, Value, HashFunc, EqualsFunc >::getCreateEntry ( const Key &  key)
inline
854  {
855  bool ignore;
856  return getCreateEntry(key, ignore);
857  }
Entry & getCreateEntry(const Key &key, bool &created)
Definition: Table.h:772
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Entry* G3D::Table< Key, Value, HashFunc, EqualsFunc >::getEntryPointer ( const Key &  key) const
inlineprivate
676  {
677  if (m_numBuckets == 0) {
678  return NULL;
679  }
680 
681  size_t code = HashFunc::hashCode(key);
682  size_t b = code % m_numBuckets;
683 
684  Node* node = m_bucket[b];
685 
686  while (node != NULL) {
687  if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
688  return &(node->entry);
689  }
690  node = node->next;
691  }
692 
693  return NULL;
694  }
size_t hashCode() const
Definition: Vector2unorm16.h:76
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
Definition: inftrees.h:24
Node * next
Definition: Table.h:129
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
const Key* G3D::Table< Key, Value, HashFunc, EqualsFunc >::getKeyPointer ( const Key &  key) const
inline

If a value that is EqualsFunc to member is present, returns a pointer to the version stored in the data structure, otherwise returns NULL.

701  {
702  const Entry* e = getEntryPointer(key);
703  if (e == NULL) {
704  return NULL;
705  } else {
706  return &(e->key);
707  }
708  }
arena_t NULL
Definition: jemalloc_internal.h:624
Entry
Definition: boss_headless_horseman.cpp:50
Entry * getEntryPointer(const Key &key) const
Definition: Table.h:676

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Array<Key> G3D::Table< Key, Value, HashFunc, EqualsFunc >::getKeys ( ) const
inline

Returns an array of all of the keys in the table. You can iterate over the keys to get the values.

Deprecated:
907  {
908  Array<Key> keyArray;
909  getKeys(keyArray);
910  return keyArray;
911  }
Array< Key > getKeys() const
Definition: Table.h:907

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::getKeys ( Array< Key > &  keyArray) const
inline
913  {
914  keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
915  for (size_t i = 0; i < m_numBuckets; ++i) {
916  Node* node = m_bucket[i];
917  while (node != NULL) {
918  keyArray.append(node->entry.key);
919  node = node->next;
920  }
921  }
922  }
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
const bool DONT_SHRINK_UNDERLYING_ARRAY
Definition: Array.h:43
Node * next
Definition: Table.h:129
size_t m_numBuckets
Definition: Table.h:197
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Value* G3D::Table< Key, Value, HashFunc, EqualsFunc >::getPointer ( const Key &  key) const
inline

Returns a pointer to the element if it exists, or NULL if it does not. Note that if your value type is a pointer, the return value is a pointer to a pointer. Do not remove the element while holding this pointer.

It is easy to accidentally mis-use this method. Consider making a Table<Value*> and using get(key, val) instead, which makes you manage the memory for the values yourself and is less likely to result in pointer errors.

731  {
732  if (m_numBuckets == 0) {
733  return NULL;
734  }
735 
736  size_t code = HashFunc::hashCode(key);
737  size_t b = code % m_numBuckets;
738 
739  Node* node = m_bucket[b];
740 
741  while (node != NULL) {
742  if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
743  // found key
744  return &(node->entry.value);
745  }
746  node = node->next;
747  }
748 
749  // Failed to find key
750  return NULL;
751  }
size_t hashCode() const
Definition: Vector2unorm16.h:76
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
Definition: inftrees.h:24
Node * next
Definition: Table.h:129
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::getRemove ( const Key &  key,
Key &  removedKey,
Value removedValue 
)
inline

If member is present, sets removed to the element being removed and returns true. Otherwise returns false and does not write to removed.

660  {
661  return remove(key, removedKey, removedValue, true);
662  }

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::getValues ( Array< Value > &  valueArray) const
inline

Will contain duplicate values if they exist in the table. This array is parallel to the one returned by getKeys() if the table has not been modified.

925  {
926  valueArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
927  for (size_t i = 0; i < m_numBuckets; ++i) {
928  Node* node = m_bucket[i];
929  while (node != NULL) {
930  valueArray.append(node->entry.value);
931  node = node->next;
932  }
933  }
934  }
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
const bool DONT_SHRINK_UNDERLYING_ARRAY
Definition: Array.h:43
Node * next
Definition: Table.h:129
size_t m_numBuckets
Definition: Table.h:197
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
template<class H , class E >
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::operator!= ( const Table< Key, Value, H, E > &  other) const
inline
991  {
992  return ! (*this == other);
993  }
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Table& G3D::Table< Key, Value, HashFunc, EqualsFunc >::operator= ( const ThisType h)
inline
346  {
347  // No need to copy if the argument is this
348  if (this != &h) {
349  // Free the existing nodes
350  freeMemory();
351  this->copyFrom(h);
352  checkIntegrity();
353  }
354  return *this;
355  }
void checkIntegrity() const
Definition: Table.h:169
void freeMemory()
Definition: Table.h:277
void copyFrom(const ThisType &h)
Definition: Table.h:252
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
template<class H , class E >
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::operator== ( const Table< Key, Value, H, E > &  other) const
inline
971  {
972  if (size() != other.size()) {
973  return false;
974  }
975 
976  for (Iterator it = begin(); it.hasMore(); ++it) {
977  const Value* v = other.getPointer(it->key);
978  if ((v == NULL) || (*v != it->value)) {
979  // Either the key did not exist or the value was not the same
980  return false;
981  }
982  }
983 
984  // this and other have the same number of keys, so we don't
985  // have to check for extra keys in other.
986 
987  return true;
988  }
size_t size() const
Definition: Table.h:589
Iterator begin() const
Definition: Table.h:562
arena_t NULL
Definition: jemalloc_internal.h:624
bool hasMore() const
Definition: Table.h:551
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Value& G3D::Table< Key, Value, HashFunc, EqualsFunc >::operator[] ( const Key &  key) const
inline

Short syntax for get.

898  {
899  return get(key);
900  }
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::remove ( const Key &  key,
Key &  removedKey,
Value removedValue,
bool  updateRemoved 
)
inlineprivate

Helper for remove() and getRemove()

606  {
607  if (m_numBuckets == 0) {
608  return false;
609  }
610 
611  const size_t code = HashFunc::hashCode(key);
612  const size_t b = code % m_numBuckets;
613 
614  // Go to the m_bucket
615  Node* n = m_bucket[b];
616 
617  if (n == NULL) {
618  return false;
619  }
620 
621  Node* previous = NULL;
622 
623  // Try to find the node
624  do {
625  if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
626  // This is the node; remove it
627 
628  // Replace the previous's next pointer
629  if (previous == NULL) {
630  m_bucket[b] = n->next;
631  } else {
632  previous->next = n->next;
633  }
634 
635  if (updateRemoved) {
636  removedKey = n->entry.key;
637  removedValue = n->entry.value;
638  }
639  // Delete the node
641  --m_size;
642 
643  //checkIntegrity();
644  return true;
645  }
646 
647  previous = n;
648  n = n->next;
649  } while (n != NULL);
650 
651  //checkIntegrity();
652  return false;
653  }
static void destroy(Node *n, MemoryManager::Ref &mm)
Definition: Table.h:156
size_t hashCode() const
Definition: Vector2unorm16.h:76
arena_t NULL
Definition: jemalloc_internal.h:624
size_t m_size
Definition: Table.h:184
Node ** m_bucket
Definition: Table.h:192
Key key
Definition: Table.h:109
uint32_t previous(octet_iterator &it, octet_iterator pass_start)
Deprecated in versions that include "prior".
Definition: checked.h:179
Definition: inftrees.h:24
Node * next
Definition: Table.h:129
Entry entry
Definition: Table.h:127
MemoryManager::Ref m_memoryManager
Definition: Table.h:199
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
bool G3D::Table< Key, Value, HashFunc, EqualsFunc >::remove ( const Key &  key)
inline

Removes an element from the table if it is present.

Returns
true if the element was found and removed, otherwise false
668  {
669  Key x;
670  Value v;
671  return remove(key, x, v, false);
672  }
G3D::int16 x
Definition: Vector2int16.h:37
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::resize ( size_t  newSize)
inlineprivate

Re-hashes for a larger m_bucket size.

212  {
213 
214  // Hang onto the old m_bucket array
215  Node** oldBucket = m_bucket;
216 
217  // Allocate a new m_bucket array with the new size
218  m_bucket = (Node**)alloc(sizeof(Node*) * newSize);
219  alwaysAssertM(m_bucket != NULL, "MemoryManager::alloc returned NULL. Out of memory.");
220  // Set all pointers to NULL
221  System::memset(m_bucket, 0, newSize * sizeof(Node*));
222  // Move each node to its new hash location
223  for (size_t b = 0; b < m_numBuckets; ++b) {
224  Node* node = oldBucket[b];
225 
226  // There is a linked list of nodes at this m_bucket
227  while (node != NULL) {
228  // Hang onto the old next pointer
229  Node* nextNode = node->next;
230 
231  // Insert at the head of the list for m_bucket[i]
232  size_t i = node->hashCode % newSize;
233  node->next = m_bucket[i];
234  m_bucket[i] = node;
235 
236  // Move on to the next node
237  node = nextNode;
238  }
239 
240  // Drop the old pointer for cleanliness when debugging
241  oldBucket[b] = NULL;
242  }
243 
244  // Delete the old storage
245  free(oldBucket);
246  this->m_numBuckets = newSize;
247 
248  checkIntegrity();
249  }
static void memset(void *dst, uint8 value, size_t numBytes)
Definition: System.cpp:695
void free(void *p) const
Definition: Table.h:205
arena_t NULL
Definition: jemalloc_internal.h:624
Node ** m_bucket
Definition: Table.h:192
void checkIntegrity() const
Definition: Table.h:169
void * alloc(size_t s) const
Definition: Table.h:201
#define alwaysAssertM(exp, message)
Definition: debugAssert.h:165
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::set ( const Key &  key,
const Value value 
)
inline

If you insert a pointer into the key or value of a table, you are responsible for deallocating the object eventually. Inserting key into a table is O(1), but may cause a potentially slow rehashing.

599  {
600  getCreateEntry(key).value = value;
601  }
Entry & getCreateEntry(const Key &key, bool &created)
Definition: Table.h:772
Value value
Definition: Table.h:110
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
void G3D::Table< Key, Value, HashFunc, EqualsFunc >::setSizeHint ( size_t  n)
inline

Recommends that the table resize to anticipate at least this number of elements.

318  {
319  size_t s = n * 3;
320  if (s > m_numBuckets) {
321  resize(s);
322  }
323  }
void resize(size_t newSize)
Definition: Table.h:212
size_t m_numBuckets
Definition: Table.h:197

+ Here is the caller graph for this function:

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
size_t G3D::Table< Key, Value, HashFunc, EqualsFunc >::size ( ) const
inline

Returns the number of keys.

589  {
590  return m_size;
591  }
size_t m_size
Definition: Table.h:184

+ Here is the caller graph for this function:

Member Data Documentation

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
Node** G3D::Table< Key, Value, HashFunc, EqualsFunc >::m_bucket
private

Array of Node*.

We don't use Array<Node*> because Table is lower-level than Array. Some elements may be NULL.

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
MemoryManager::Ref G3D::Table< Key, Value, HashFunc, EqualsFunc >::m_memoryManager
private
template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
size_t G3D::Table< Key, Value, HashFunc, EqualsFunc >::m_numBuckets
private

Length of the m_bucket array.

template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key>>
size_t G3D::Table< Key, Value, HashFunc, EqualsFunc >::m_size
private

Number of elements in the table.


The documentation for this class was generated from the following file: