//===- HashBase.h ---------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_HASH_BASE_H
#define MCLD_HASH_BASE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <llvm/ADT/StringRef.h>
#include <cstdlib>
namespace mcld {
/** forward declaration **/
template<typename HashTableImplTy>
class ChainIteratorBase;
template<typename HashTableImplTy>
class EntryIteratorBase;
/** \class HashBucket
* \brief HashBucket is an entry in the hash table.
*/
template<typename HashEntryTy>
class HashBucket
{
public:
typedef HashEntryTy entry_type;
public:
unsigned int FullHashValue;
entry_type *Entry;
public:
static entry_type* getEmptyBucket();
static entry_type* getTombstone();
};
/** \class HashTableImpl
* \brief HashTableImpl is the base class of HashTable.
*
* HashTableImpl uses open-addressing, linear probing hash table.
* linear probing hash table obviously has high performance when the
* load factor is less than 0.7.
* The drawback is that the number of the stored items can notbe more
* than the size of the hash table.
*
* MCLinker tries to merge every things in the same HashEntry. It can
* keep every thing in the same cache line and improve the locality
* efficiently. HashTableImpl provides a template argument to change the
* definition of HashEntries.
*
* HashEntryTy must provide getKey() and getKenLength() functions.
*
* Different environments have different demands of HashFunctions. For
* example, on-device linkers needs a more light-weight hash function
* than static linkers. HashTableImpl also provides a template argument to
* change the hash functions.
*/
template<typename HashEntryTy,
typename HashFunctionTy>
class HashTableImpl
{
private:
static const unsigned int NumOfInitBuckets = 16;
public:
typedef size_t size_type;
typedef HashFunctionTy hasher;
typedef HashEntryTy entry_type;
typedef typename HashEntryTy::key_type key_type;
typedef HashBucket<HashEntryTy> bucket_type;
typedef HashTableImpl<HashEntryTy, HashFunctionTy> Self;
public:
HashTableImpl();
explicit HashTableImpl(unsigned int pInitSize);
virtual ~HashTableImpl();
// ----- observers ----- //
bool empty() const;
size_t numOfBuckets() const
{ return m_NumOfBuckets; }
size_t numOfEntries() const
{ return m_NumOfEntries; }
hasher& hash()
{ return m_Hasher; }
const hasher& hash() const
{ return m_Hasher; }
protected:
/// initialize the hash table.
void init(unsigned int pInitSize);
/// lookUpBucketFor - search the index of bucket whose key is p>ey
// @return the index of the found bucket
unsigned int lookUpBucketFor(const key_type& pKey);
/// findKey - finds an element with key pKey
// return the index of the element, or -1 when the element does not exist.
int findKey(const key_type& pKey) const;
/// mayRehash - check the load_factor, compute the new size, and then doRehash
void mayRehash();
/// doRehash - re-new the hash table, and rehash all elements into the new buckets
void doRehash(unsigned int pNewSize);
friend class ChainIteratorBase<Self>;
friend class ChainIteratorBase<const Self>;
friend class EntryIteratorBase<Self>;
friend class EntryIteratorBase<const Self>;
protected:
// Array of Buckets
bucket_type* m_Buckets;
unsigned int m_NumOfBuckets;
unsigned int m_NumOfEntries;
unsigned int m_NumOfTombstones;
hasher m_Hasher;
};
#include "HashBase.tcc"
} // namespace of mcld
#endif