Remove non-portable dependencies from SimplerHash.
authorPat Gavlin <pagavlin@microsoft.com>
Thu, 31 Mar 2016 22:59:27 +0000 (15:59 -0700)
committerPat Gavlin <pagavlin@microsoft.com>
Wed, 6 Apr 2016 16:35:09 +0000 (09:35 -0700)
- Remove contracts. Pre- and post-conditions have been replaced
  with asserts.
- Hang the "no memory" callback off of Behavior instead of
  calling ThrowOutOfMemory directly
- Remove operator new overloads that defer to the global
  operator new.

Commit migrated from https://github.com/dotnet/coreclr/commit/6863ed8cf37548c198cd64db06b3d59431e7e873

src/coreclr/src/inc/simplerhash.h
src/coreclr/src/inc/simplerhash.inl

index 60f4c1d..49cf096 100644 (file)
@@ -2,22 +2,9 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-// ==++==
-// 
-
-//
-
-// 
-// ==--==
-
-
 #ifndef _SIMPLERHASHTABLE_H_
 #define _SIMPLERHASHTABLE_H_
 
-// #include "utilcode.h" // for string hash functions
-// #include "clrtypes.h"
-// #include "check.h"
-// #include "iterator.h"
 #include "iallocator.h"
 
 // SimplerHashTable implements a mapping from a Key type to a Value type,
 // 
 // The "Behavior" argument provides the following static members:
 //
-// static const bool s_NoThrow                  true if GetKey, Equals, and hash are NOTHROW functions.  
-//                                              Affects the THROWS clauses of several SHash functions.
-//                                              (Note that the Null- and Deleted-related functions below 
-//                                              are not affected by this and must always be NOTHROW.)
-//
 // s_growth_factor_numerator
 // s_growth_factor_denominator                  Factor to grow allocation (numerator/denominator).  
 //                                              Typically inherited from default traits (3/2)
 //                                              probably preferable to call Reallocate on initialization rather
 //                                              than override his from the default traits. (7)
 //
+// NoMemory()                                   Called when the has table is unable to grow due to potential
+//                                              overflow or the lack of a sufficiently large prime.
 
-
+void DECLSPEC_NORETURN ThrowOutOfMemory();
 
 class DefaultSimplerHashBehavior
 {
-  public:
+public:
     static const unsigned s_growth_factor_numerator = 3;
     static const unsigned s_growth_factor_denominator = 2;
 
@@ -74,13 +58,14 @@ class DefaultSimplerHashBehavior
 
     static const unsigned s_minimum_allocation = 7;
 
-    static const bool s_NoThrow = true;
+    inline static void DECLSPEC_NORETURN NoMemory()
+    {
+        ::ThrowOutOfMemory();
+    }
 };
 
-
-// stores info about primes, including the magic number and shift amount needed
+// Stores info about primes, including the magic number and shift amount needed
 // to implement a divide without using the divide instruction
-
 class PrimeInfo
 {
 public:
@@ -97,8 +82,7 @@ public:
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 class SimplerHashTable
 {
-  public:
-
+public:
     // Forward declaration.
     class KeyIterator;
 
@@ -110,56 +94,6 @@ class SimplerHashTable
     SimplerHashTable(IAllocator* alloc);
     ~SimplerHashTable();
 
-    // We wish to provide overloaded operator new/deletes that take an
-    // "IAllocator", so that an shash may be dynamically allocated
-    // using a non-standard allocator.  If we do so, and in some
-    // contexts still want to use the default operator new, C++ also requires us
-    // to declare overloads for the standard new and delete operators.
-
-    void * operator new(size_t sz)
-    {
-        CONTRACTL
-        {
-            THROWS;
-            GC_NOTRIGGER;
-        }
-        CONTRACTL_END;
-        return ::operator new(sz);
-    }
-
-    void * operator new(size_t sz, const NoThrow& tothrow)
-    {
-        CONTRACTL
-        {
-            if (nothrow.x== tothrow.x)NOTHROW; else THROWS;
-            GC_NOTRIGGER;
-        }
-        CONTRACTL_END;
-        return ::operator new(sz, tothrow);
-    }
-
-    void   operator delete(void* p)
-    {
-        CONTRACTL
-        {
-            NOTHROW;
-            GC_NOTRIGGER;
-        }
-        CONTRACTL_END;
-        ::operator delete(p);
-    }
-
-    void   operator delete[](void* p)
-    {
-        CONTRACTL
-        {
-            NOTHROW;
-            GC_NOTRIGGER;
-        }
-        CONTRACTL_END;
-        ::operator delete[](p);
-    }
-
     // operators new/delete when an IAllocator is to be used.
     void * operator new(size_t sz, IAllocator * alloc);
     void * operator new[](size_t sz, IAllocator * alloc);
@@ -173,8 +107,6 @@ class SimplerHashTable
 
     Value *LookupPointer(Key k) const;
 
-    unsigned GetIndexForKey(Key k) const;
-
     // Causes the table to map "key" to "val".  Returns "true" if
     // "key" had already been mapped by the table, "false" otherwise.
     bool Set(Key k, Value val);
@@ -183,10 +115,6 @@ class SimplerHashTable
     // Returns "true" iff it had been mapped.
     bool Remove(Key k);
 
-    // Remove the mapping to which the current iterator "points"
-    // (i.e., will yield).
-    void Remove(KeyIterator& i);
-
     // Remove all mappings in the table.
     void RemoveAll();
 
@@ -197,11 +125,12 @@ class SimplerHashTable
     // Return the number of elements currently stored in the table
     unsigned GetCount() const; 
 
-  private:
-
+private:
     // Forward declaration of the linked-list node class.
     struct Node;
 
+    unsigned GetIndexForKey(Key k) const;
+
     // If the table has a mapping for "k", return the node containing
     // that mapping, else "NULL".
     Node* FindNode(Key k) const;
@@ -214,8 +143,7 @@ class SimplerHashTable
     // the hash table.
     void CheckGrowth();
 
-  public:
-
+public:
     // Reallocates a hash table to a specific size.  The size must be big enough
     // to hold all elements in the table appropriately.  
     //
@@ -234,10 +162,9 @@ class SimplerHashTable
     // }
     // iter.Get() will yield (a reference to) the
     // current key.  It will assert the equivalent of "iter != end."
-    //
-
     class KeyIterator
     {
+    private:
         friend class SimplerHashTable;
 
         // The method implementations have to be here for portability.
@@ -248,15 +175,13 @@ class SimplerHashTable
         unsigned    m_tableSize;
         unsigned    m_index;
 
-      public:
-
+    public:
         KeyIterator(const SimplerHashTable *hash, BOOL begin)
         : m_table(hash->m_table),
           m_node(NULL),
           m_tableSize(hash->m_tableSizeInfo.prime),
           m_index(begin ? 0 : m_tableSize)
         {
-            LIMITED_METHOD_CONTRACT;
             if (begin && hash->m_tableCount > 0)
             {
                 assert(m_table != NULL);
@@ -277,8 +202,6 @@ class SimplerHashTable
 
         const Key& Get() const
         {
-            LIMITED_METHOD_CONTRACT;
-
             assert(m_node != NULL);
 
             return m_node->m_key;
@@ -286,8 +209,6 @@ class SimplerHashTable
 
         const Value& GetValue() const
         {
-            LIMITED_METHOD_CONTRACT;
-
             assert(m_node != NULL);
 
             return m_node->m_val;
@@ -295,8 +216,6 @@ class SimplerHashTable
 
         void SetValue(const Value & value) const
         {
-            LIMITED_METHOD_CONTRACT;
-
             assert(m_node != NULL);
 
             m_node->m_val = value;
@@ -304,8 +223,6 @@ class SimplerHashTable
 
         void Next()
         {
-            LIMITED_METHOD_CONTRACT;
-
             if (m_node != NULL)
             {
                 m_node = m_node->m_next;
@@ -334,18 +251,13 @@ class SimplerHashTable
 
         bool Equal(const KeyIterator &i) const
         { 
-            LIMITED_METHOD_CONTRACT;
             return i.m_node == m_node; 
         }
 
-        CHECK DoCheck() const
-        {
-            CHECK_OK;
-        }
-
         void operator++() {
             Next();
         }
+
         void operator++(int) {
             Next();
         }
@@ -392,13 +304,10 @@ class SimplerHashTable
     }
 
   private:
-
     // Find the next prime number >= the given value.  
-
     static PrimeInfo NextPrime(unsigned number);
 
     // Instance members
-
     IAllocator*   m_alloc;                // IAllocator to use in this
                                           // table.
     // The node type.
@@ -451,8 +360,6 @@ public:
     }
 };
 
-
-
 template<typename T> // Must be coercable to "unsigned" with no loss of information.
 struct SmallPrimitiveKeyFuncs: public KeyFuncsDefEquals<T>
 {
index 091f047..dc72acb 100644 (file)
@@ -2,23 +2,9 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-// ==++==
-// 
-
-// 
-
-//
-// ==--==
-
 #ifndef _SIMPLERHASHTABLE_INL_
 #define _SIMPLERHASHTABLE_INL_
 
-// Many SimplerHashTable functions do not throw on their own, but may propagate an exception
-// from Hash, Equals, or GetKey.
-#define NOTHROW_UNLESS_BEHAVIOR_THROWS     if (Behavior::s_NoThrow) NOTHROW; else THROWS
-
-void DECLSPEC_NORETURN ThrowOutOfMemory();
-
 // To implement magic-number divide with a 32-bit magic number,
 // multiply by the magic number, take the top 64 bits, and shift that
 // by the amount given in the table.
@@ -49,8 +35,6 @@ SimplerHashTable<Key,KeyFuncs,Value,Behavior>::SimplerHashTable(IAllocator* allo
     m_tableCount(0),
     m_tableMax(0)
 {
-    LIMITED_METHOD_CONTRACT;
-
     assert(m_alloc != nullptr);
 
 #ifndef __GNUC__ // these crash GCC
@@ -62,78 +46,42 @@ SimplerHashTable<Key,KeyFuncs,Value,Behavior>::SimplerHashTable(IAllocator* allo
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 SimplerHashTable<Key,KeyFuncs,Value,Behavior>::~SimplerHashTable()
 {
-    LIMITED_METHOD_CONTRACT;
-
     RemoveAll();
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void * SimplerHashTable<Key,KeyFuncs,Value,Behavior>::operator new(size_t sz, IAllocator * alloc)
 {
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-    }
-    CONTRACTL_END;
     return alloc->Alloc(sz);
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void * SimplerHashTable<Key,KeyFuncs,Value,Behavior>::operator new[](size_t sz, IAllocator * alloc)
 {
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-    }
-    CONTRACTL_END;
     return alloc->Alloc(sz);
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::operator delete(void * p, IAllocator * alloc)
 {
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-    }
-    CONTRACTL_END;
     alloc->Free(p);
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::operator delete[](void * p, IAllocator * alloc)
 {
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-    }
-    CONTRACTL_END;
     alloc->Free(p);
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 unsigned SimplerHashTable<Key,KeyFuncs,Value,Behavior>::GetCount() const 
 {
-    LIMITED_METHOD_CONTRACT;
-
     return m_tableCount;
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 bool SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Lookup(Key key, Value* pVal) const
 {
-    CONTRACTL
-    {
-        NOTHROW_UNLESS_BEHAVIOR_THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACTL_END;
-
     Node* pN = FindNode(key);
 
     if (pN != NULL)
@@ -153,14 +101,6 @@ bool SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Lookup(Key key, Value* pVal)
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 Value *SimplerHashTable<Key,KeyFuncs,Value,Behavior>::LookupPointer(Key key) const
 {
-    CONTRACTL
-    {
-        NOTHROW_UNLESS_BEHAVIOR_THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACTL_END;
-
     Node* pN = FindNode(key);
 
     if (pN != NULL)
@@ -173,38 +113,28 @@ template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 typename SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Node*
 SimplerHashTable<Key,KeyFuncs,Value,Behavior>::FindNode(Key k) const
 {
-    CONTRACT(Node*)
-    {
-        NOTHROW_UNLESS_BEHAVIOR_THROWS;
-        GC_NOTRIGGER;
-        POSTCONDITION(RETVAL == NULL || KeyFuncs::Equals(k, RETVAL->m_key));
-    }
-    CONTRACT_END;
-
     if (m_tableSizeInfo.prime == 0)
-        RETURN NULL;
+        return NULL;
 
     unsigned index = GetIndexForKey(k);
 
     Node* pN = m_table[index];
-    if (pN == NULL) RETURN NULL;
+    if (pN == NULL)
+        return NULL;
+
     // Otherwise...
     while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key))
         pN = pN->m_next;
+
+    assert(pN == NULL || KeyFuncs::Equals(k, pN->m_key));
+
     // If pN != NULL, it's the node for the key, else the key isn't mapped.
-    RETURN pN;    
+    return pN;
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 unsigned SimplerHashTable<Key,KeyFuncs,Value,Behavior>::GetIndexForKey(Key k) const
 {
-    CONTRACTL
-    {
-        NOTHROW_UNLESS_BEHAVIOR_THROWS;
-        GC_NOTRIGGER;
-    }
-    CONTRACTL_END;
-
     unsigned hash = KeyFuncs::GetHashCode(k);
     
     unsigned index = magicNumberRem(hash, m_tableSizeInfo);
@@ -215,14 +145,6 @@ unsigned SimplerHashTable<Key,KeyFuncs,Value,Behavior>::GetIndexForKey(Key k) co
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 bool SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Set(Key k, Value v)
 {
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACTL_END;
-
     CheckGrowth();
 
     assert(m_tableSizeInfo.prime != 0);
@@ -251,14 +173,6 @@ bool SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Set(Key k, Value v)
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 bool SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Remove(Key k)
 {
-    CONTRACTL
-    {
-        NOTHROW_UNLESS_BEHAVIOR_THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACTL_END;
-
     unsigned index = GetIndexForKey(k);
 
     Node* pN = m_table[index];
@@ -281,38 +195,9 @@ bool SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Remove(Key k)
     }
 }
 
-// TBD
-template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
-void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Remove(KeyIterator& i)
-{
-#if 0
-    CONTRACT_VOID
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-        PRECONDITION(s_supports_remove);
-        PRECONDITION(!(IsNull(*i)));
-        PRECONDITION(!(IsDeleted(*i)));
-    }
-    CONTRACT_END;
-
-    RemoveElement(m_table, m_tableSize, (element_t*)&(*i));
-#endif
-    return;
-}
-
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::RemoveAll()
 {
-    CONTRACT_VOID
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACT_END;
-
     for (unsigned i = 0; i < m_tableSizeInfo.prime; i++)
     {
         for (Node* pN = m_table[i]; pN != NULL; )
@@ -329,14 +214,12 @@ void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::RemoveAll()
     m_tableCount = 0;
     m_tableMax = 0;
 
-    RETURN;
+    return;
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 typename SimplerHashTable<Key,KeyFuncs,Value,Behavior>::KeyIterator SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Begin() const
 {
-    LIMITED_METHOD_CONTRACT;
-
     KeyIterator i(this, TRUE);
     return i;
 }
@@ -344,22 +227,12 @@ typename SimplerHashTable<Key,KeyFuncs,Value,Behavior>::KeyIterator SimplerHashT
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 typename SimplerHashTable<Key,KeyFuncs,Value,Behavior>::KeyIterator SimplerHashTable<Key,KeyFuncs,Value,Behavior>::End() const
 {
-    LIMITED_METHOD_CONTRACT;
-
     return KeyIterator(this, FALSE);
 }
 
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::CheckGrowth()
 {
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACTL_END;
-
     if (m_tableCount == m_tableMax)
     {
         Grow();
@@ -369,14 +242,6 @@ void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::CheckGrowth()
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Grow()
 {
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-    }
-    CONTRACTL_END;
-
     unsigned newSize = (unsigned) (m_tableCount 
                                    * Behavior::s_growth_factor_numerator / Behavior::s_growth_factor_denominator
                                    * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator);
@@ -385,7 +250,7 @@ void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Grow()
 
     // handle potential overflow
     if (newSize < m_tableCount)
-        ThrowOutOfMemory();
+        Behavior::NoMemory();
 
     Reallocate(newSize);
 }
@@ -393,15 +258,7 @@ void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Grow()
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 void SimplerHashTable<Key,KeyFuncs,Value,Behavior>::Reallocate(unsigned newTableSize)
 {
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-        INSTANCE_CHECK;
-        PRECONDITION(newTableSize >= 
-                     (GetCount() * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator));
-    }
-    CONTRACTL_END;
+    assert(newTableSize >= (GetCount() * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator));
 
     // Allocation size must be a prime number.  This is necessary so that hashes uniformly
     // distribute to all indices, and so that chaining will visit all indices in the hash table.
@@ -481,20 +338,13 @@ SELECTANY const PrimeInfo primeInfo[] =
 template <typename Key, typename KeyFuncs, typename Value, typename Behavior>
 PrimeInfo SimplerHashTable<Key,KeyFuncs,Value,Behavior>::NextPrime(unsigned number)
 {
-    CONTRACT(PrimeInfo)
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-    }
-    CONTRACT_END;
-
     for (int i = 0; i < (int) (sizeof(primeInfo) / sizeof(primeInfo[0])); i++) {
         if (primeInfo[i].prime >= number)
-            RETURN primeInfo[i];
+            return primeInfo[i];
     }
 
     // overflow
-    ThrowOutOfMemory();
+    Behavior::NoMemory();
 }
 
 #endif // _SIMPLERHASHTABLE_INL_