c++簡單的線程安全HashMap

說明:主要是記錄自己的練習,不保證正確,請勿參考,且沒有達到容量上限時自動擴容和重新hash

 

#ifndef THREADSAFEHASHMAP_H
#define THREADSAFEHASHMAP_H
#include<functional>
#include<mutex>
#include<utility>
#include<list>
#include<algorithm>
#include<iostream>
#include<vector>
#include<memory>
#include<map>

namespace com{
    namespace example{
        namespace testone{
            namespace thread{
                namespace data_structures{




template<typename K, typename V, typename Hash = std::hash<K>>
class ThreadSafeHashMap
{
    private:

        class BucketType{
            public:
                typedef std::pair<K, V> BucketValue;
                typedef std::list<BucketValue> BucketData;
                typedef typename std::list<BucketValue>::iterator BucketIterator;
                BucketData mData;
                std::mutex mtx;

            public:
                bool checkIsFind(const BucketValue& bv, const K& key){
                    if(bv.first == key){
                        return true;
                    }
                    return false;
                }

                BucketIterator findByKey(const K& key){
                    //std::bind中的佔位符_1,調用的時候由調用方傳入,調用方傳入的第一個參數替換_1
                    //本里中調用方傳入的是BucketValue
                    auto it = std::find_if(this->mData.begin(), this->mData.end(),
                                            std::bind(&BucketType::checkIsFind, this, std::placeholders::_1, key));
                    return it;
                }

                V get(const K& key, V defaultValue){
                    std::lock_guard<std::mutex> lk(this->mtx);
                    BucketIterator it = this->findByKey(key);
                    if(it != this->mData.end()){
                        return it->second;
                    }
                    return defaultValue;
                }

                void removeByKey(const K& key){
                    std::lock_guard<std::mutex> lk(this->mtx);
                    BucketIterator it = this->findByKey(key);
                    if(it != this->mData.end()){
                        this->mData.erase(it);
                    }
                }

                void addOrUpdata(K key, V value){
                    std::lock_guard<std::mutex> lk(this->mtx);
                    //std::cout << "addOrUpdata(K key, V value)開始" << std::endl;
                    BucketIterator it = this->findByKey(key);
                    if(it != this->mData.end()){ //找到了就更新
                        //std::cout << "addOrUpdata(K key, V value)....找到了更新" << std::endl;
                        *it = std::move(std::pair<K, V>(std::move(key), std::move(value)));
                    }else{ //沒找到就插入
                        //std::pair<K, V> p(std::move(key), std::move(value));
                        //std::cout << "addOrUpdata(K key, V value)....未找到插入" << std::endl;
                        this->mData.push_back(std::pair<K, V>(std::move(key), std::move(value)));
                    }

                }


        };

    public:
        ThreadSafeHashMap(int num = 19, Hash hasher = Hash()){
            //this->mBuckets = std::vector<std::shared_ptr<BucketType>>(num);
            this->mHasher = std::move(hasher);
            for(int i = 0; i < num; i++){
                this->mBuckets.push_back(std::shared_ptr<BucketType>(new BucketType));
            }
            //std::cout << "ThreadSafeHashMap()......mBuckets.size() = " << this->mBuckets.size() << std::endl;
        }
        virtual ~ThreadSafeHashMap(){

        }
    public:
        void addOrUpdateMy(K key, V value){
            //std::shared_ptr<BucketType> sp = this->positeByHash(key);
            this->positeByHash(key)->addOrUpdata(key, value);
        }

        V getMy(const K& key, V value){
            return this->positeByHash(key)->get(key, value);
        }

        void removeMy(const K& key){
            this->positeByHash(key)->removeByKey(key);
        }

        /**
        * 這個需要要把每一個BucketType都鎖住,防止獲取的時候有BucketType在修改
        */
        std::map<K, V> getAll(){
            //將每一個BucketType都鎖住
            std::vector<std::unique_lock<std::mutex>> mtxs;
            for(int i = 0; i < this->mBuckets.size(); i++){
                mtxs.push_back(std::move(std::unique_lock<std::mutex>(this->mBuckets.at(i)->mtx)));
            }
            //循環遍歷取出內容
            std::map<K, V> mapTmp;
            for(int i = 0; i < this->mBuckets.size(); i++){
                std::shared_ptr<BucketType> sp = this->mBuckets.at(i);
                std::list<std::pair<K, V>>& bd = sp->mData;
                for(auto it = bd.begin(); it != bd.end(); it++){
                    mapTmp.insert(*it);
                }
            }
            return mapTmp;

        }

    protected:

    private:
        /**
        * 根據key計算hash值,根據hash值計算在vecotr中對應位置的BucketType
        */
        std::shared_ptr<BucketType> positeByHash(const K& key){
            std::size_t h = this->mHasher(key) % this->mBuckets.size();
            //std::cout << "positeByHash(const K& key)....h = " << h << std::endl;
            //std::cout << "this->mBuckets.size() = " << this->mBuckets.size() << std::endl;
            return this->mBuckets.at(h);
        }

    private:
        std::vector<std::shared_ptr<BucketType>> mBuckets;
        Hash mHasher;


};







                }
            }
        }
    }
}

#endif // THREADSAFEHASHMAP_H

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章