在写dl engine的时候,一直不想依赖于其它库,但hash map这种常用的map肯定会经常用到,而stl的hash_map非线程安全,就打算自已把stl 的hash map或者ACE的hash map改写一下。因为最近一直在用ACE做项目,对ACE_Hash_Map_ManagerEx比较熟悉,就把它的源码看了几遍,发现ACE的hash map和stl的实现差不多,都是用桶开链法实现,不同点就在于ace的hash map好像没有在hash负载较高的时候,像stl那样会重新找一个接近元素数量的质数再重新分配(不知道我有没有看漏)。下面源码把只是把ace hash map常用的方法改写,不常用的干掉。只实现一部分功能。而类型萃取type_trait这些都没改写。因为我没用到,有用到的时候再写
/*
* hash_map.hpp
*
* Created on: 2012-7-27
* Author: QS
*/
#ifndef HASH_MAP_HPP_
#define HASH_MAP_HPP_
#include "hash_map_entry.hpp"
#include "hash_map_iterator_base.hpp"
#include "hash_map_algorithm.hpp"
#include "../lock/RWLock.h"
#include "../Util.h"
#include <strings.h>
#include <stdlib.h>
namespace DL
{
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
class hash_map
{
friend class hash_map_iterator_base<Key, Value, Lock, Hash, Equal> ;
public:
typedef Key key_type;
typedef Value date_type;
typedef hash_map_entry<Key, Value> value_type;
typedef value_type &reference;
typedef value_type const &const_reference;
typedef value_type *pointer;
typedef value_type const *const_pointer;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef hash_map_iterator<Key, Value, Lock, Hash, Equal> iterator;
typedef hash_map_const_iterator<Key, Value, Lock, Hash, Equal> const_iterator;
public:
hash_map(int init_size);
~hash_map();
int bind(Key key, Value value);
int unbind(Key key);
int unbind_all(void);
int find(const Key &key, Value &value);
iterator begin(void);
iterator end(void);
const_iterator begin(void) const;
const_iterator end(void) const;
Lock &mutex(void);
protected:
int __find_location(const Key &key, hash_map_entry<Key, Value> *&entry, int &loc);
int __bind(Key key, Value value);
int __unbind(Key key);
int __unbind_all(void);
int __find(const Key &key, Value &value);
int hash(Key key);
int equal(const Key &key_one, const Key &key_two);
int create_bucket(int size);
private:
int __total_size;
int __cur_size;
Lock __lock;
Hash __hash;
Equal __compare;
DL::hash_map_entry<Key, Value> *__table;
};
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
hash_map<Key, Value, Lock, Hash, Equal>::hash_map(int init_size) :
__total_size(0), __cur_size(0)
{
this->create_bucket(init_size);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
hash_map<Key, Value, Lock, Hash, Equal>::~hash_map()
{
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::create_bucket(int size)
{
int bytes = size * sizeof(hash_map_entry<Key, Value> );
this->__table = (hash_map_entry<Key, Value>*) malloc(bytes);
this->__total_size = size;
for (int i = 0; i < this->__total_size; i++)
{
new (&__table[i]) hash_map_entry<Key, Value> (&__table[i], &__table[i]);
}
return 0;
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::bind(Key key, Value value)
{
//lock
WriteGurad<Lock> lock(this->__lock);
return this->__bind(key, value);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::unbind(Key key)
{
//lock
WriteGurad<Lock> lock(this->__lock);
return this->__unbind(key);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::unbind_all(void)
{
//lock
WriteGurad<Lock> lock(this->__lock);
return this->__unbind_all();
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::find(const Key &key, Value &value)
{
//lock
ReadGurad<Lock> lock(this->__lock);
return this->__find(key, value);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
typename hash_map<Key, Value, Lock, Hash, Equal>::iterator hash_map<Key, Value, Lock, Hash, Equal>::begin(void)
{
return iterator(*this);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
typename hash_map<Key, Value, Lock, Hash, Equal>::iterator hash_map<Key, Value, Lock, Hash, Equal>::end(void)
{
return iterator(*this, 1);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
typename hash_map<Key, Value, Lock, Hash, Equal>::const_iterator hash_map<Key, Value, Lock, Hash, Equal>::begin(void) const
{
return const_iterator(*this);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
typename hash_map<Key, Value, Lock, Hash, Equal>::const_iterator hash_map<Key, Value, Lock, Hash, Equal>::end(void) const
{
return const_iterator(*this, 1);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::__find_location(const Key &key, hash_map_entry<Key, Value> *&entry, int &loc)
{
JUDGE_RETURN(this->__total_size != 0,-1);
loc = this->hash(key) % this->__total_size;
hash_map_entry<Key, Value> *temp = this->__table[loc].__next;
while (temp != &this->__table[loc] && this->equal(temp->__key, key) == 0)
{
temp = temp->__next;
}
if (temp == &this->__table[loc])
{
return -1;
}
else
{
entry = temp;
return 0;
}
return 1;
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::__bind(Key key, Value value)
{
int loc = 0;
hash_map_entry<Key, Value> *entry = NULL;
if (this->__find_location(key, entry, loc) == -1)
{
void *ptr = malloc(sizeof(hash_map_entry<Key, Value> ));
bzero(ptr, sizeof(hash_map_entry<Key, Value> ));
entry = new (ptr) hash_map_entry<Key, Value> (this->__table[loc].__next, &this->__table[loc]);
entry->init(key, value);
this->__table[loc].__next = entry;
entry->__next->__prev = entry;
this->__cur_size++;
return 0;
}
return 1;
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::__unbind(Key key)
{
hash_map_entry<Key, Value> *entry = NULL;
int loc = 0;
if (this->__find_location(key, entry, loc) == -1)
{
return -1;
}
entry->__next->__prev = entry->__prev;
entry->__prev->__next = entry->__next;
entry->~hash_map_entry<Key, Value> ();
free(entry);
this->__cur_size--;
return 0;
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::__unbind_all(void)
{
for (size_t i = 0; i < this->__total_size; i++)
{
hash_map_entry<Key, Value> *ptr = this->__table[i].__next;
for (; ptr != &this->__table[i];)
{
hash_map_entry<Key, Value> *slot_ptr = ptr;
ptr = ptr->__next;
slot_ptr->~hash_map_entry<Key, Value> ();
free(slot_ptr);
}
this->__table[i].__next_ = &this->__table[i];
this->__table[i].__prev = &this->__table[i];
}
return 0;
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::__find(const Key &key, Value &value)
{
hash_map_entry<Key, Value> *entry = 0;
int loc = 0;
if (this->__find_location(key, entry, loc) == -1)
{
return -1;
}
else
{
value = entry->__value;
return 0;
}
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::hash(Key key)
{
return this->__hash(key);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
int hash_map<Key, Value, Lock, Hash, Equal>::equal(const Key &key_one, const Key &key_two)
{
return this->__compare(key_one, key_two);
}
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
Lock &hash_map<Key, Value, Lock, Hash, Equal>::mutex(void)
{
return this->__lock;
}
}
;
#endif /* HASH_MAP_HPP_ */
/*
* hash_map_entry.hpp
*
* Created on: 2012-7-27
* Author: QS
*/
#ifndef HASH_MAP_ENTRY_HPP_
#define HASH_MAP_ENTRY_HPP_
namespace DL
{
template<typename Key, typename Value>
class hash_map_entry
{
public:
hash_map_entry(hash_map_entry<Key, Value> *next, hash_map_entry<Key, Value> *prev)
{
this->__next = next;
this->__prev = prev;
}
virtual ~hash_map_entry()
{
}
int init(Key key, Value value)
{
this->__key = key;
this->__value = value;
return 0;
}
public:
hash_map_entry<Key, Value> *__next;
hash_map_entry<Key, Value> *__prev;
Key __key;
Value __value;
};
}
#endif /* HASH_MAP_ENTRY_HPP_ */
/*
* hash_map_iterator_base.hpp
*
* Created on: 2012-7-27
* Author: QS
*/
#ifndef HASH_MAP_ITERATOR_BASE_HPP_
#define HASH_MAP_ITERATOR_BASE_HPP_
namespace DL
{
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
class hash_map;
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
class hash_map_iterator_base
{
public:
typedef hash_map<Key, Value, Lock, Hash, Equal> container_type;
typedef typename hash_map<Key, Value, Lock, Hash, Equal>::value_type value_type;
typedef typename hash_map<Key, Value, Lock, Hash, Equal>::reference reference;
typedef typename hash_map<Key, Value, Lock, Hash, Equal>::pointer pointer;
typedef typename hash_map<Key, Value, Lock, Hash, Equal>::difference_type difference_type;
hash_map_iterator_base(hash_map<Key, Value, Lock, Hash, Equal> &hash_map, bool head)
{
this->__hash_map = &hash_map;
this->__index = head ? -1 : hash_map.__total_size;
this->__next = &hash_map.__table[head ? 0 : hash_map.__total_size - 1];
}
hash_map_iterator_base(hash_map<Key, Value, Lock, Hash, Equal> &hash_map, hash_map_entry<Key, Value> *entry, int index);
int next(hash_map_entry<Key, Value> *&entry) const
{
if (this->__hash_map->__table != 0 && this->__index < this->__hash_map->__total_size && this->__index >= 0 && this->__next
!= &this->__hash_map->__table[this->__index])
{
entry = this->__next;
return 1;
}
else
return 0;
}
int done(void) const
{
return 0;
}
hash_map_entry<Key, Value> &operator*(void) const
{
hash_map_entry<Key, Value> *retv = 0;
this->next(retv);
return *retv;
}
hash_map_entry<Key, Value> *operator->(void) const
{
hash_map_entry<Key, Value> *retv = 0;
this->next(retv);
return retv;
}
protected:
int forward(void)
{
if (this->__hash_map == 0)
return -1;
else if (this->__index == -1)
{
this->__index++;
return this->forward();
}
else if (this->__index >= this->__hash_map->__total_size)
return 0;
this->__next = this->__next->__next;
if (this->__next == &this->__hash_map->__table[this->__index])
{
while (++this->__index < this->__hash_map->__total_size)
{
this->__next = this->__hash_map->__table[this->__index].__next;
if (this->__next != &this->__hash_map->__table[this->__index])
break;
}
}
return this->__index < this->__hash_map->__total_size;
}
int reverse(void)
{
return 0;
}
protected:
hash_map<Key, Value, Lock, Hash, Equal> *__hash_map;
int __index;
hash_map_entry<Key, Value> *__next;
};
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
class hash_map_const_iterator_base
{
public:
typedef hash_map<Key, Value, Lock, Hash, Equal> contianer_type;
typedef typename contianer_type::value_type value_type;
typedef typename contianer_type::reference reference;
typedef typename contianer_type::pointer pointer;
typedef typename contianer_type::difference_type difference_type;
hash_map_const_iterator_base(contianer_type &hash_map, bool head)
{
}
hash_map_const_iterator_base(contianer_type &hash_map, hash_map_entry<Key, Value> *entry, int index)
{
}
int next(hash_map_entry<Key, Value> *&entry) const
{
return 0;
}
int done(void) const;
hash_map_entry<Key, Value> &operator*(void) const;
hash_map_entry<Key, Value> *operator->(void) const;
};
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
class hash_map_iterator: public hash_map_iterator_base<Key, Value, Lock, Hash, Equal>
{
public:
typedef hash_map_iterator<Key, Value, Lock, Hash, Equal> self_type;
typedef hash_map_iterator_base<Key, Value, Lock, Hash, Equal> super;
typedef typename super::container_type container_type;
public:
hash_map_iterator(container_type &container, int tail = 0) :
super(container, tail == 0 ? 1 : 0)
{
if (tail == 0)
{
this->forward();
}
}
self_type &operator++(void)
{
this->forward();
return *this;
}
self_type operator++(int)
{
self_type retv(*this);
++*this;
return retv;
}
self_type &operator--(void)
{
this->reverse();
return *this;
}
self_type operator--(int)
{
self_type retv(*this);
--*this;
return retv;
}
};
template<typename Key, typename Value, typename Lock, typename Hash, typename Equal>
class hash_map_const_iterator: public hash_map_const_iterator_base<Key, Value, Lock, Hash, Equal>
{
public:
typedef hash_map_const_iterator<Key, Value, Lock, Hash, Equal> self_type;
typedef hash_map_const_iterator_base<Key, Value, Lock, Hash, Equal> super;
typedef typename super::container_type container_type;
public:
hash_map_const_iterator(container_type &container, int tail = 0) :
super(container, tail == 0 ? 1 : 0)
{
if (tail == 0)
{
this->forward();
}
}
};
}
;
#endif /* HASH_MAP_ITERATOR_BASE_HPP_ */
/*
* hash_map_algorithm.hpp
*
* Created on: 2012-8-7
* Author: QS
*/
#ifndef HASH_MAP_ALGORITHM_HPP_
#define HASH_MAP_ALGORITHM_HPP_
namespace DL
{
template<typename T>
class hash
{
public:
int operator ()(const T &t) const
{
return static_cast<int> (t);
}
};
template<typename T>
class equal
{
public:
bool operator ()(const T &lhs, const T &rhs) const
{
return lhs == rhs;
}
};
}
;
#endif /* HASH_MAP_ALGORITHM_HPP_ */