A parallel hash table. Properties:
More...
#include <ParallelHashTable.h>
Inherits gts::AlignedAllocator< GTS_NO_SHARING_CACHE_LINE_SIZE >.
|
class | const_iterator |
| A constant forward iterator. Read-locks the referenced element until destruction. More...
|
|
class | iterator |
| A forward iterator. Write-locks the referenced element until destruction. More...
|
|
|
using | key_type = TKey |
|
using | mapped_type = TValue |
|
using | value_type = KeyValue< key_type, mapped_type > |
|
using | size_type = size_t |
|
using | allocator_type = TAllocator |
|
using | hasher_type = THasher |
|
|
| ParallelHashTable (allocator_type const &allocator=allocator_type()) |
|
| ParallelHashTable (uint32_t growMutexCount, allocator_type const &allocator=allocator_type()) |
|
| ~ParallelHashTable () |
|
| ParallelHashTable (ParallelHashTable const &other) |
|
| ParallelHashTable (ParallelHashTable &&other) |
|
ParallelHashTable & | operator= (ParallelHashTable const &other) |
|
ParallelHashTable & | operator= (ParallelHashTable &&other) |
|
const_iterator | cbegin () const |
|
const_iterator | cend () const |
|
iterator | begin () const |
|
iterator | end () const |
|
size_type | capacity () const |
|
size_type | max_size () const |
|
const_iterator | cfind (key_type const &key) const |
|
iterator | find (key_type const &key) |
|
allocator_type | get_allocator () const |
| Get this Vectors allocator. More...
|
|
void | reserve (size_type sizePow2) |
|
iterator | insert (value_type const &keyVal) |
|
iterator | insert (value_type &&keyVal) |
|
iterator | insert_or_assign (value_type const &keyVal) |
|
iterator | insert_or_assign (value_type &&keyVal) |
|
size_type | erase (key_type const &key) |
|
iterator | erase (iterator &iter) |
|
void | cleanup () |
|
void | clear () |
|
template<bool useLocks> |
bool | _tryGrowTable (table_type *pTable, size_type sizePow2) |
|
template<bool useLocks, typename... TArgs> |
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::iterator | _tryInsert (bool assignable, TKey const &key, TArgs &&... args) |
|
template<bool useLocks, typename... TArgs> |
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::ProbeResult | _probeWrite (bool assignable, TKey const &key, table_type *&pOutTable, size_type &outIndex) |
|
|
class | base_const_iterator |
|
class | const_iterator |
|
class | iterator |
|
template<typename TKey, typename TValue, typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
class gts::ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >
A parallel hash table. Properties:
- Open addressing with O(log2*log2(N)) probing.
- Grows when insert probing reaches O(log2*log2(N)).
- Unbound.
- Reference Stable.
- Linearizable if Mutexes are fair.
- User is responsible for calling cleanup() to delete stale tables after table doubling.
- Iterators contain spin-locks that are unlocked in the iterator's destructor. Holding onto them may cause deadlocks.
- Bad hash functions may cause huge tables. Author has only had this occur with pathologically bad hashers.
- Template Parameters
-
TKey | The unique identifier associated with each element in the container. |
TValue | The element type stored in the container. |
THasher | The hashing function. |
TAccessorSharedMutex | The shared mutex type to access individual elements. |
TGrowSharedMutex | The shared mutex type used to grow the table. |
TAllocator | The allocator used by the storage backing. |
- Todo:
Try Robin Hood hashing. (Lock cost may be prohibitive.)
Try Striped locks to protect slots instead of locks per slot.
Try 1-byte per table entry trick and use SSE for compares. (see Skarupke and Kulukundis)
Implement table shrinking.
Divise a reclaimation system (hazard pointers etc.) the avoid the need for cleanup().
Add equals template parameter.
Add size() and empty()? requires shared counter :(
◆ ParallelHashTable() [1/4]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
Constructs an empty container with the given 'allocator'. The number of striped mutexes is equal to the number of HW threads on the machine.
◆ ParallelHashTable() [2/4]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
gts::ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::ParallelHashTable |
( |
uint32_t |
growMutexCount, |
|
|
allocator_type const & |
allocator = allocator_type() |
|
) |
| |
|
explicit |
Constructs an empty container with 'growMutexCount' striped mutexes and with the given 'allocator'.
◆ ~ParallelHashTable()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable::~ParallelHashTable |
( |
| ) |
|
Destructs the container. The destructors of the elements are called and the used storage is deallocated.
◆ ParallelHashTable() [3/4]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable::ParallelHashTable |
( |
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator > const & |
other | ) |
|
Copy constructor. Constructs the container with the copy of the contents of 'other'.
◆ ParallelHashTable() [4/4]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable::ParallelHashTable |
( |
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator > && |
other | ) |
|
Move constructor. Constructs the container with the contents of other using move semantics. After the move, other is invalid.
◆ begin()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::iterator ParallelHashTable::begin |
( |
| ) |
const |
- Returns
- An iterator to the beginning of the current hash table state.
◆ capacity()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::size_type ParallelHashTable::capacity |
( |
| ) |
const |
- Returns
- The total number of slots in the table.
◆ cbegin()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
- Returns
- An iterator to the beginning of the current hash table state.
◆ cend()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
- Returns
- An iterator to the end of the current hash table state.
◆ cfind()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::const_iterator ParallelHashTable::cfind |
( |
key_type const & |
key | ) |
const |
Finds an element with key equivalent to 'key'.
- Returns
- A const_terator to an element with key equivalent to key. If no such element is found, past-the-end (see end()) iterator is returned.
◆ cleanup()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
void ParallelHashTable::cleanup |
( |
| ) |
|
Destroys old table memory.
◆ clear()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
void ParallelHashTable::clear |
( |
| ) |
|
Clear the data from the table.
◆ end()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::iterator ParallelHashTable::end |
( |
| ) |
const |
- Returns
- An iterator to the end of the current hash table state.
◆ erase() [1/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
Erases the element referenced by 'iter' and invalidates 'iter'.
- Returns
- The next iterator.
◆ erase() [2/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
size_type gts::ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::erase |
( |
key_type const & |
key | ) |
|
Tries to erase an element from the table.
- Returns
- The number if element erased.
◆ find()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::iterator ParallelHashTable::find |
( |
key_type const & |
key | ) |
|
Finds an element with key equivalent to 'key'.
- Returns
- An iterator to an element with key equivalent to key. If no such element is found, past-the-end (see end()) iterator is returned.
◆ get_allocator()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::allocator_type ParallelHashTable::get_allocator |
( |
| ) |
const |
Get this Vectors allocator.
- Returns
- The allocator.
◆ insert() [1/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
Inserts an element into the container, if the container doesn't already contain an element with an equivalent key.
- Returns
- An iterator to the element if it's inserted successfully, or past-the-end (see end()) iterator if: (1) The key already exists. (2) The table failed to grow.
◆ insert() [2/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
Inserts an element into the container, if the container doesn't already contain an element with an equivalent key.
- Returns
- An iterator to the element if it's inserted successfully, or past-the-end (see end()) iterator if: (1) The key already exists. (2) The table failed to grow.
◆ insert_or_assign() [1/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
Inserts an element into the container or assign the new value if it already exists.
- Returns
- An iterator to the element if it's inserted successfully, or past-the-end (see end()) iterator if the table failed to grow.
◆ insert_or_assign() [2/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
Inserts an element into the container or assign the new value if it already exists.
- Returns
- An iterator to the element if it's inserted successfully, or past-the-end (see end()) iterator if the table failed to grow.
◆ max_size()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator >::size_type ParallelHashTable::max_size |
( |
| ) |
const |
- Returns
- Maximum number of slots the container can grow to.
◆ operator=() [1/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator > & ParallelHashTable::operator= |
( |
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator > && |
other | ) |
|
Move assignment operator. Replaces the contents with those of other using move semantics. After the move, other is invalid.
◆ operator=() [2/2]
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator > & ParallelHashTable::operator= |
( |
ParallelHashTable< TKey, TValue, THasher, TAccessorSharedMutex, TGrowSharedMutex, TAllocator > const & |
other | ) |
|
Copy assignment operator. Replaces the contents with a copy of the contents of 'other'.
◆ reserve()
template<typename TKey , typename TValue , typename THasher = MurmurHash<TKey>, typename TAccessorSharedMutex = UnfairSharedSpinMutex<>, typename TGrowSharedMutex = UnfairSharedSpinMutex<>, typename TAllocator = AlignedAllocator<GTS_NO_SHARING_CACHE_LINE_SIZE>>
void ParallelHashTable::reserve |
( |
size_type |
sizePow2 | ) |
|
Increases the capacity of the hash table. Does nothing if 'sizePow2' < capacity.