[mathic] 29/62: Changed HashTable interface: Node is now Handle (name might change again soon), and use of 'combine' is now gone.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Wed Apr 1 11:36:20 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch master
in repository mathic.

commit c4d5bc5c1eaa9b656b90e6ccc82f125c669c8446
Author: Mike Stillman <mikestillman1 at gmail.com>
Date:   Sat Aug 4 08:00:21 2012 -0400

    Changed HashTable interface: Node is now Handle (name might change again soon), and use of 'combine' is now gone.
---
 src/mathic/HashTable.h | 92 ++++++++++++++++++++++++++------------------------
 src/test/HashTable.cpp | 45 +++++++++++++++++++++---
 2 files changed, 89 insertions(+), 48 deletions(-)

diff --git a/src/mathic/HashTable.h b/src/mathic/HashTable.h
index 7691669..339946f 100644
--- a/src/mathic/HashTable.h
+++ b/src/mathic/HashTable.h
@@ -32,7 +32,6 @@ namespace mathic {
 
     size_t hash(Key k);
     bool keysEqual(Key k1, Key k2);
-    void combine(Value &a, const Value &b);
   };
 
   template<class Configuration> 
@@ -57,10 +56,22 @@ namespace mathic {
     // If 'remove' returns a Node*, then it is safe to change the key and/or value, e.g.
     //  to free the space pointed to by 'key' (if that is a pointer value, for instance).
 
-    struct Node {
-      Node *next;
-      Key key;
-      Value value;
+    class Handle {
+    public:
+      friend class HashTable;
+
+      Handle(Key k, Value v):
+	next(0),
+	entry(k,v)
+      {}
+
+      const Key& key() const {return entry.first;}
+      const Value& value() const {return entry.second;}
+      Value& value() {return entry.second;}
+      void setKeyButOnlyDoSoIfThisHandleIsNotInHashTable(Key &new_k) {entry.first=new_k;}
+    private:
+      Handle *next;
+      std::pair<Key, Value> entry;
     };
 
     // Create a hash table
@@ -75,22 +86,17 @@ namespace mathic {
     Configuration const& configuration() const {return mConf;}
 
     // insert the key 'k' into the hash table.  If the key is already there,
-    // call C.combine on the old and new values.
-    // If combine returns false, then remove the node from the hash table.
     // and return std::pair(false, ...)
     // else return std::pair(true, node in the hash table).
-    std::pair<bool, Node*> insert(Key const& k, Value const& v);
+    std::pair<bool, Handle*> insert(Key const& k, Value const& v);
 
     // If 'k' is present in the hash table, then its 'Node*' is returned.
     // If not, then NULL is returned.
-    Node* lookup(const Key &k);
+    Handle* lookup(const Key &k);
 
-    // remove 'p' from the hash table.  'p' itself is not removed???!
-    void remove(Node* p);
-
-    const Key& key(Node* p) const {return p->key;}
-
-    const Value& value(Node* p) const {return p->value;}
+    // remove 'p' from the hash table.  'p' itself is also removed.
+    // what about the entries in 'p'?  Are the destructors called?
+    void remove(Handle* & p);
 
     void reset(); // Major assumption: all nodes have been removed from the table already
 
@@ -105,7 +111,7 @@ namespace mathic {
     std::string name() const;
 
   private:
-    Node* makeNode(const Key &k, const Value &v);
+    Handle* makeNode(const Key &k, const Value &v);
 
     void grow(unsigned int nbits);
 
@@ -132,7 +138,7 @@ namespace mathic {
     bool mAlwaysInsertAtEnd;
 
     memt::BufferPool mNodePool;
-    std::vector<Node *> mHashTable;
+    std::vector<Handle *> mHashTable;
     Configuration mConf;
   };
 
@@ -145,7 +151,7 @@ namespace mathic {
     mBinCount(0),
     mRebuildThreshold(0.1),
     mAlwaysInsertAtEnd(true),
-    mNodePool(sizeof(Node)),
+    mNodePool(sizeof(Handle)),
     mConf(conf) 
   {
     mHashTable.resize(mTableSize);
@@ -160,24 +166,22 @@ namespace mathic {
   }
 
   template<class C>
-  typename HashTable<C>::Node *HashTable<C>::makeNode(const Key &k, const Value &v)
+  typename HashTable<C>::Handle *HashTable<C>::makeNode(const Key &k, const Value &v)
   {
     mNodeCount++;
-    Node *result = static_cast<Node *>(mNodePool.alloc());
-    result->next = 0;
-    result->key = k;
-    result->value = v;
+    void *buf = mNodePool.alloc();
+    Handle* result = new (buf) Handle(k,v);
     return result;
   }
 
   template<class C>
-  std::pair<bool, typename HashTable<C>::Node *> HashTable<C>::insert(const Key &k, const Value &v) 
+  std::pair<bool, typename HashTable<C>::Handle *> HashTable<C>::insert(const Key &k, const Value &v) 
   {
     size_t hashval = mConf.hash(k) & mHashMask;
     
     MATHIC_ASSERT(hashval < mHashTable.size());
-    Node *tmpNode = mHashTable[hashval];
-    Node *result = 0;
+    Handle *tmpNode = mHashTable[hashval];
+    Handle *result = 0;
     if (tmpNode == 0)
       {
 	result = makeNode(k,v);
@@ -187,11 +191,10 @@ namespace mathic {
       {
 	while (true)
 	  {
-	    if (mConf.keysEqual(tmpNode->key, k))
+	    if (mConf.keysEqual(tmpNode->key(), k))
 	      {
-		mConf.combine(tmpNode->value, v);
 		result = tmpNode;
-		return std::pair<bool,Node *>(false,result);
+		return std::pair<bool,Handle *>(false,result);
 	      }
 	    if (tmpNode->next == 0)
 	      {
@@ -216,38 +219,39 @@ namespace mathic {
       grow(mLogTableSize + 2);  // increase by a factor of 4??
     
     MATHIC_ASSERT(computeNodeCount() == mNodeCount);
-    return std::pair<bool, Node *>(true,result);
+    return std::pair<bool, Handle *>(true,result);
   }
 
   template<class C>
-  typename HashTable<C>::Node * HashTable<C>::lookup(const Key &k)
+  typename HashTable<C>::Handle * HashTable<C>::lookup(const Key &k)
   {
     size_t hashval = mConf.hash(k) & mHashMask;
     
     MATHIC_ASSERT(hashval < mHashTable.size());
-    for (Node *p = mHashTable[hashval]; p != 0; p = p->next)
+    for (Handle *p = mHashTable[hashval]; p != 0; p = p->next)
       {
-	if (mConf.keysEqual(p->key, k))
+	if (mConf.keysEqual(p->key(), k))
 	  return p;
       }
     return NULL;
   }
     
   template<class C>
-  void HashTable<C>::remove(Node *p) 
+  void HashTable<C>::remove(Handle *& p) 
   {
     mNodeCount--;
     size_t const hashval = mConf.hashvalue(p->key) & mHashMask;
-    Node head;
-    Node* tmpNode = mHashTable[hashval];
+    Handle head;
+    Handle* tmpNode = mHashTable[hashval];
     head.next = tmpNode;
-    for (Node* q = &head; q->next != 0; q = q->next) 
+    for (Handle* q = &head; q->next != 0; q = q->next) 
       {
 	if (q->next == p) 
 	  {
 	    q->next = p->next;
 	    mHashTable[hashval] = head.next;
 	    if (head.next == 0) mBinCount--;
+	    //TODO: call destructor for pair, then call 'free' with the mNodePool
 	    return;
 	  }
       }
@@ -266,21 +270,21 @@ namespace mathic {
     mTableSize = static_cast<size_t>(1) << new_nbits;
     mLogTableSize = new_nbits;
     mHashMask = mTableSize-1;
-    std::vector<Node *> old_table(mTableSize);
+    std::vector<Handle *> old_table(mTableSize);
     std::swap(old_table, mHashTable);
 
     mBinCount = 0;
     for (size_t i = 0; i < old_table_size; ++i)
       {
-	Node *p = old_table[i];
+	Handle *p = old_table[i];
 	while (p != 0)
 	  {
-	    Node *q = p;
+	    Handle *q = p;
 	    p = p->next;
 	    q->next = 0;
 	    // Reinsert node.  We know that it is unique
-	    size_t hashval = mConf.hash(q->key) & mHashMask;
-	    Node *r = mHashTable[hashval];
+	    size_t hashval = mConf.hash(q->key()) & mHashMask;
+	    Handle *r = mHashTable[hashval];
 	    if (r == 0) mBinCount++;
 	    if (r == 0 || !mAlwaysInsertAtEnd) 
 	      {
@@ -305,7 +309,7 @@ namespace mathic {
   template<class C>
   size_t HashTable<C>::memoryUse() const
   {
-    size_t result = mHashTable.capacity() * sizeof(Node *);
+    size_t result = mHashTable.capacity() * sizeof(Handle *);
     result += mNodePool.getMemoryUse();
     return result;
   }
@@ -316,7 +320,7 @@ namespace mathic {
     size_t result = 0;
     for (size_t i=0; i<mTableSize; i++)
       {
-	for (Node *p = mHashTable[i]; p != 0; p = p->next) result++;
+	for (Handle *p = mHashTable[i]; p != 0; p = p->next) result++;
       }
     return result;
   }
diff --git a/src/test/HashTable.cpp b/src/test/HashTable.cpp
index 17bb4c1..1c94c8f 100755
--- a/src/test/HashTable.cpp
+++ b/src/test/HashTable.cpp
@@ -1,5 +1,6 @@
 #include "mathic/HashTable.h"
 #include <gtest/gtest.h>
+#include <tr1/functional>
 
 namespace {
   class HashTableConf 
@@ -10,7 +11,6 @@ namespace {
 
     size_t hash(Key k) {return k;}
     bool keysEqual(Key k1, Key k2) {return k1==k2;}
-    void combine(Value &a, const Value &b){a+=b;}
   };
 
   typedef mathic::HashTable<HashTableConf> HashTab;
@@ -25,9 +25,46 @@ TEST(HashTable, NoOp) {
   H.insert(17,7);
   H.insert(14,4);
 
-  HashTab::Node *p = H.lookup(14);
+  HashTab::Handle *p = H.lookup(14);
   ASSERT_FALSE(p == NULL);
-  ASSERT_EQ(p->key,14);
-  ASSERT_EQ(p->value,11);
+  ASSERT_EQ(p->key(),14);
+  ASSERT_EQ(p->value(),7);
+};
+
+namespace {
+  class HashTableStringConf 
+  {
+  public:
+    typedef std::string Key;
+    typedef size_t Value;
+    typedef std::tr1::hash<std::string> hashfcn;
+    size_t hash(Key k) { 
+      hashfcn fcn; 
+      return fcn(k);
+    }
+
+    bool keysEqual(Key k1, Key k2) {return k1==k2;}
+  };
+
+  typedef mathic::HashTable<HashTableStringConf> HashStringTab;
+}
+
+TEST(HashTable, StringKeys) {
+  HashTableStringConf C;
+  HashStringTab H(C);
+
+
+  H.insert("hi there",3);
+  H.insert("whooa",7);
+  H.insert("whoah",7);
+  H.insert("hi there",4);
+
+  HashStringTab::Handle *p = H.lookup("hi there");
+  ASSERT_FALSE(p == NULL);
+  ASSERT_EQ(p->key(),"hi there");
+  ASSERT_EQ(p->value(),3);
+
+  p = H.lookup("hi There");
+  ASSERT_TRUE(p == NULL);
 };
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathic.git



More information about the debian-science-commits mailing list