您的位置:首页 > 编程语言 > Go语言

Algorithm: 简单的并发Hash-Map

2016-11-22 00:00 330 查看
#include <list>
#include <mutex>
#include <vector>
#include <utility>
#include <string>
#include <iostream>
#include <memory>
#include <type_traits>
#include <initializer_list>
#include <unordered_map>

//BOOST
#include <boost/optional.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>

template<typename Key,  typename Value,
typename Hash=std::hash<Key>>
class HashContainer {
private:

//HashMap中的桶.
template<typename KeyT, typename ValueT>
class Bucket {
public:
using BucketValue = std::pair<KeyT, ValueT>; //桶中的Key-Val
using BucketData = std::list<BucketValue>; //Key-Val被存放在 list 中.
using ConstIterator = typename BucketData::const_iterator;
using Iterator = typename BucketData::iterator;

Bucket() = default;
Bucket(const Bucket<KeyT, ValueT>&) = delete;
Bucket<KeyT, ValueT>& operator=(const Bucket<KeyT, ValueT>&) = delete;

//通过key查找对应的值.
std::pair<bool, ValueT> findValue(const Key& key)const
{
boost::shared_lock<boost::shared_mutex> sharedL{ this->sharedM };

const Iterator itr = this->findFromKey(key);
return ((itr == this->data.end()) ? std::pair<bool, ValueT>{false, ValueT{}} : std::pair<bool, ValueT>{true, itr->second});
}

//添加key-value到hash-map中.
void addValue(const KeyT& key, const ValueT& value) //针对: lvalue
{
std::unique_lock<boost::shared_mutex> uniqueL{ this->sharedM };
const Iterator itr = this->findFromKey(key);

this->addValueToContainer(key, value, itr); //注意这里!
}

//添加key-value到hash-map中.
void addValue(KeyT&& key, ValueT&& value) //针对: rvalue
{
std::unique_lock<boost::shared_mutex> uniqueL{ this->sharedM };
const Iterator itr = this->findFromKey(key);

this->addValueToContainer(std::move(key), std::move(value), itr); //注意这里!
}

//通过key来移除hash-map中的:key-value.
void removeValue(const KeyT& key)
{
std::unique_lock<boost::shared_mutex> uniqueL{ this->sharedM };

ConstIterator itr = this->findFromKey(key);
if (itr = (this->data).cend()) {
(this->data).erase(itr);
}
}

private:

const Iterator findFromKey(const KeyT& key)
{
const Iterator cbeg = (this->data).begin(); //const Iterator其实相当于:ValueT* const ptr 是一个顶层const.
const Iterator cend = (this->data).end();

const Iterator itr = std::find_if(cbeg, cend,
[&key](const BucketValue& value)->bool { return (value.first == key) ? true : false; });

return itr;
}

template<typename K, typename V>
void addValueToContainer(K&& key, V&& value, const Iterator itr) //完美转发插入的值.
{
if (itr == (this->data).cend()) {
(this->data).push_back(std::pair<KeyT, ValueT>{std::forward<K>(key), std::forward<V>(value)});

} else {
itr->second = std::forward<V>(value);

}
}

BucketData data;
mutable boost::shared_mutex sharedM{}; //Notice that.
};

public:
using KeyType = Key;
using ValueType = Value;
using HashType = Hash;

HashContainer(const std::size_t& size = 19)try //notice that.
: bucketNumbers(size)
{
std::lock_guard<std::mutex> locGuard{ this->mutex };
this->initialContainer();

}catch (const std::out_of_range& error) {
std::cout << error.what() << std::endl;
}

~HashContainer() = default;

//Notice that.
HashContainer(const HashContainer<Key, Value>&) = delete;
HashContainer<Key, Value>& operator=(const HashContainer<Key, Value>&) = delete;

std::size_t bucketNumber()const noexcept
{
return (this->buckets).size();
}

template<typename K, typename V>
void insert(K&& key, V&& value)
{
std::size_t hashVal = this->hashValue(key, typename std::is_class<Hash>::type{}); //标签分配.

Bucket<Key, Value>& bucket = this->getBucket(hashVal);
bucket.addValue(std::forward<K>(key), std::forward<V>(value));
}

void erase(const Key& key)
{
std::size_t hashVal = this->hashValue(key);

Bucket<Key, Value>& bucket = this->getBucket(hashVal);
bucket.removeValue(key);
}

private:
std::size_t hashValue(const Key& key, std::true_type) const noexcept
{
std::size_t hashVal{};
hashVal = this->hasher(key) % (this->bucketNumber());

return hashVal; //相当于返回 std::move(hashVal);
}

std::size_t hashValue(const Key& key, std::false_type)const noexcept
{
std::size_t hashVal{};
hashVal = *(this->hasher)(key) % (this->bucketNumber());

return hashVal;  //相当于返回 std::move(hashVal);
}

Bucket<Key, Value>& getBucket(const std::size_t& size)noexcept
{
return (*(this->buckets)[size]);
}

void initialContainer()
{
if (this->bucketNumbers == 0) {
throw std::out_of_range("out of range!");

} else {
for (unsigned int i = 0; i < (this->bucketNumbers); ++i) {
buckets.push_back(std::unique_ptr<Bucket<Key, Value>>{new Bucket<Key, Value>{}});
}

buckets.shrink_to_fit();
}
}

Hash hasher{};
std::mutex mutex{};
std::size_t bucketNumbers{ 19 };   //初始桶的个数为19个.
std::vector<std::unique_ptr<Bucket<Key, Value>>>  buckets{};
};

int main()
{

HashContainer<int, int> container{};
container.insert(1, 20);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: