unordered_map thread safety

后端 未结 7 688
故里飘歌
故里飘歌 2020-11-30 02:12

I am changing a single thread program into multi thread using boost:thread library. The program uses unordered_map as a hasp_map for lookups. My question is..

At on

相关标签:
7条回答
  • 2020-11-30 03:16

    If you don't need all of the functionality of unordered_map, then this solution should work for you. It uses mutex to control access to the internal unordered_map. The solution supports the following methods, and adding more should be fairly easy:

    • getOrDefault(key, defaultValue) - returns the value associated with key, or defaultValue if no association exists. A map entry is not created when no association exists.
    • contains(key) - returns a boolean; true if the association exists.
    • put(key, value) - create or replace association.
    • remove(key) - remove association for key
    • associations() - returns a vector containing all of the currently known associations.

    Sample usage:

    /* SynchronizedMap
    ** Functional Test
    ** g++ -O2 -Wall -std=c++11 test.cpp -o test
    */
    #include <iostream>
    #include "SynchronizedMap.h"
    
    using namespace std;
    using namespace Synchronized;
    
    int main(int argc, char **argv) {
    
        SynchronizedMap<int, string> activeAssociations;
    
        activeAssociations.put({101, "red"});
        activeAssociations.put({102, "blue"});
        activeAssociations.put({102, "green"});
        activeAssociations.put({104, "purple"});
        activeAssociations.put({105, "yellow"});
        activeAssociations.remove(104);
    
        cout << ".getOrDefault(102)=" << activeAssociations.getOrDefault(102, "unknown") << "\n";
        cout << ".getOrDefault(112)=" << activeAssociations.getOrDefault(112, "unknown") << "\n";
    
        if (!activeAssociations.contains(104)) {
            cout << 123 << " does not exist\n";
        }
        if (activeAssociations.contains(101)) {
            cout << 101 << " exists\n";
        }
    
        cout << "--- associations: --\n";
        for (auto e: activeAssociations.associations()) {
            cout << e.first << "=" << e.second << "\n";
        }
    }
    

    Sample output:

    .getOrDefault(102)=green
    .getOrDefault(112)=unknown
    123 does not exist
    101 exists
    --- associations: --
    105=yellow
    102=green
    101=red
    

    Note1: The associations() method is not intended for very large datasets as it will lock the table during the creation of the vector list.

    Note2: I've purposefully not extended unordered_map in order to prevent my self from accidentally using a method from unordered_map that has not been extended and therefore might not be thread safe.

    #pragma once
    /*
     * SynchronizedMap.h
     * Wade Ryan 20200926
     * c++11
     */
    
    #include <unordered_map>
    #include <mutex>
    #include <vector>
    
    #ifndef __SynchronizedMap__
    #define __SynchronizedMap__
    
    using namespace std;
    
    
    namespace Synchronized {
    
        template <typename KeyType, typename ValueType>
    
        class SynchronizedMap {
    
        private:
            mutex sync;
            unordered_map<KeyType, ValueType> usermap;    
    
        public:
            ValueType getOrDefault(KeyType key, ValueType defaultValue) {
                sync.lock();
    
                ValueType rs;
    
                auto value=usermap.find(key);
                if (value == usermap.end()) {
                    rs = defaultValue;
                } else {
                    rs = value->second;
                }
                sync.unlock();
                return rs;
            }
    
            bool contains(KeyType key) {
                sync.lock();
                bool exists = (usermap.find(key) != usermap.end());
                sync.unlock();
                return exists;
            }
    
            void put(pair<KeyType, ValueType> nodePair) {
                sync.lock();
    
                if (usermap.find(nodePair.first) != usermap.end()) {
                    usermap.erase(nodePair.first);
                }
                usermap.insert(nodePair);
                sync.unlock();
            }
    
            void remove(KeyType key) {
                sync.lock();
    
                if (usermap.find(key) != usermap.end()) {
                    usermap.erase(key);
                }
                sync.unlock();
            }
    
            vector<pair<KeyType, ValueType>> associations() {
                sync.lock();
     
                vector<pair<KeyType, ValueType>> elements;
    
                for (auto it=usermap.begin(); it != usermap.end(); ++it) {
                    pair<KeyType, ValueType> element (it->first, it->second);
                    elements.push_back( element );
                }
    
                sync.unlock();
                return elements;
            }
        };       
    }
    
    #endif
    
    0 讨论(0)
提交回复
热议问题