hash table在nebula中的使用场景主要用于string的高速缓存,hash函数我们采用了murmur3,经测试,该hash table的插入和删除效率是stl中unordered_map的2倍左右,查找的效率比unordered_map略高。考虑堆内存分配的性能问题,我们自定义了一个内存池以快速分配容器所需的内存,该hash表是自动扩展,是全完全跨平台的, 以下为源代码:
//
// hashtable.h
// nebula
//
// Created by yi.cheng on 15/12/31.
// Copyright © 2015 kanshansoft. All rights reserved.
//
#ifndef hashtable_h
#define hashtable_h
#include
#include
#include
#include
namespace anysee {
template
inline uint32_t hashfunc(const K& key) { return key.hash(); } template<> inline uint32_t hashfunc(const char* const& key) { return hash_murmur2((uint8_t*)key, strlen(key)); } template<> inline uint32_t hashfunc(char* const& key) { return hash_murmur2((uint8_t*)key, strlen(key)); } template<> inline uint32_t hashfunc(const uint32_t& key) { return nba_inthash_u32(key); } template<> inline uint32_t hashfunc(const int& key) { return nba_inthash_u32((uint32_t)key); } template<> inline uint32_t hashfunc(const uint64_t& key) { return nba_inthash_u6432(key); } template<> inline uint32_t hashfunc(const int64_t& key) { return nba_inthash_u6432((uint64_t)key); } template
struct HashKeyType { typedef K OrignType; typedef K Type; }; template <> struct HashKeyType
{ typedef const char* OrignType; typedef anysee::String8 Type; }; template <> struct HashKeyType
{ typedef char* OrignType; typedef anysee::String8 Type; }; template <> struct HashKeyType
{ typedef IOString orignType; typedef anysee::String8 Type; }; template
class HashTable { HashTable(const HashTable&); HashTable& operator = (const HashTable&); /* * One element in the list. */ class BNode { public: inline BNode(const K& key, const V& val, uint32_t hkey) : mKey(key), mVal(val), mHKey(hkey), mpNext(NULL) {} ~BNode() {} inline V& getValue() { return mVal; } inline typename HashKeyType
::Type& getKey() { return mKey; } inline const V& getValue() const { return mVal; } inline const typename HashKeyType
::Type& getKey() const { return mKey; } inline BNode* getNext() const { return mpNext; } inline void setVal(const V& val) { mVal = val; } inline void setNext(BNode* ptr) { mpNext = ptr; } private: friend class HashTable; typename HashKeyType
::Type mKey; V mVal; uint32_t mHKey; BNode* mpNext; }; public: HashTable(); bool insert(const K& key, const V& value); V* const find(const K& key); bool remove(const K& key); inline uint32_t size() const { return mSize; } void clear(); ~HashTable(); private: uint32_t mSize; uint32_t mBucketMax; uint32_t mBucketMask; uint32_t mLogSize; BNode** mBuckets; alloctor mAlloctor; void __grow(); }; template
HashTable
::HashTable(): mSize(0) { if (N < 16) { mBucketMax = 16; } else { mBucketMax = nba_roundup_pow2_u32(N); } mLogSize = ilog2_u32(mBucketMax); mBucketMask = mBucketMax -1; //initialize buckets mBuckets = (BNode**)mAlloctor.malloc(mBucketMax*sizeof(BNode*)); memset(mBuckets, 0, mBuck