[PATCH] D22681: [esan] Add generic resizing hashtable

Derek Bruening via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 2 12:15:21 PDT 2016


bruening added inline comments.

================
Comment at: lib/esan/esan_hashtable.h:24
@@ +23,3 @@
+// KeyTy must have an operator== and an operator size_t() (for hashing).
+// Pointer types will be automatically de-referenced prior to either operator==
+// or a size_t hash cast.
----------------
aizatsky wrote:
> bruening wrote:
> > aizatsky wrote:
> > > aizatsky wrote:
> > > > Key pointer types...
> > > I actually wonder if this is a functionality you want to build in rather then provide through type traits.
> > > 
> > > Like this:
> > > 
> > > template <typename KeyTy, typename DataTy, typename KeyTraits = DefaultTraits<KeyTy>>
> > > 
> > > And later something like:
> > > 
> > > KeyTraits::hash(key)
> > > KeyTraits::eq(key1, key2).
> > > 
> > Could you elaborate on what the pros and cons of your proposal are?  I assume you mean that we define DefaultTraits to invoke operator== and operator size_t() and the point here is to let the user separate hashing from casting and key equality from some other equality -- though the existing constructor takes in an optional hash function for that purpose, and I'm not sure equality would need to be separated.
> Pros:
> 
> - makes HashTable simpler
> - moves type-based decision into a much-much simpler class 
> - type-based decision can be made explicit. Consider:
> 
>   HashTable<int*, int> vs HashTable<int*, int, DerefPointers>
> 
> I would also suggest to move HashFunc to the trait as well. This would improve performance of the hashing.
> 
> The only const that I see is that you need to define a default trait struct. But that looks more like a pro to me :)
I agree that the table would be improved to move the hash function and comparison function into template parameters, but I'd prefer to not combine them, which forces a user who wants to set just one to define both.

I still like a default that de-references pointers, but after removing the payload-freeing function parameter and relying on the user using a smart pointer to free, and considering that in C++ the payload is easily copied into the hashtable entry structure via templates (unlike C where indirection via a pointer into the heap is the typical solution), which means that the payload is less likely to be a pointer, and references means that the key is also less likely to be a pointer (yes still more of a C programmer than a C++ programmer), I'm fine removing it.

================
Comment at: lib/esan/esan_hashtable.h:28
@@ +27,3 @@
+// synchronization for payloads once hashtable functions return.  If
+// ExternalLock is set to true, the caller should call the lock() and unlock()
+// routines around all hashtable operations and subsequent manipulation of
----------------
aizatsky wrote:
> Again, I don't like that there's a conditional branch throughout the class based on the field.
> 
> The most logical way to me would be to define HashTable without any synchronization (i.e. ExternalLock = true), and create a SynchronizedHashTable : public HashTable with corresponding overrides.
The problem is that inheritance means we pay virtual dispatch costs, while a container (i.e., SynchronizedHashTable contains a HashTable inside it) just means a lot of duplicated boilerplate to wrap everything.  I instead made the ExternalLock a template parameter and thus constant at compile time, which eliminates the conditional branches.


https://reviews.llvm.org/D22681





More information about the llvm-commits mailing list