我需要建立一个线程安全的映射,我的意思是每个值必须是独立互斥的。例如,我需要能够同时从两个不同的线程获得map["abc"]和map["vf"]。
我的想法是制作两张地图:一张是数据,另一张是互斥键:
class cache
{
private:
....
std::map<std::string, std::string> mainCache;
std::map<std::string, std::unique_ptr<std::mutex> > mutexCache;
std::mutex gMutex;
.....
public:
std::string get(std::string key);
};
std::string cache::get(std::string key){
std::mutex *m;
gMutex.lock();
if (mutexCache.count(key) == 0){
mutexCache.insert(new std::unique_ptr<std::mutex>);
}
m = mutexCache[key];
gMutex.unlock();
}我发现我无法从字符串创建到互斥对象的映射,因为在std::mutex中没有复制构造函数,我必须使用std::unique_ptr;但是当我编译它时,我得到:
/home/user/test/cache.cpp:7: error: no matching function for call to 'std::map<std::basic_string<char>, std::unique_ptr<std::mutex> >::insert(std::unique_ptr<std::mutex>*)'
mutexCache.insert(new std::unique_ptr<std::mutex>);
^我该如何解决这个问题?
发布于 2014-08-28 09:01:20
将mutexCache.insert(new std::unique_ptr<std::mutex>)替换为:
mutexCache.emplace(key, new std::mutex);在C++14中,您应该说:
mutexCache.emplace(key, std::make_unique<std::mutex>());但是,整个代码非常杂乱无章,不优雅。应该是这样的:
std::string cache::get(std::string key)
{
std::mutex * inner_mutex;
{
std::lock_guard<std::mutex> g_lk(gMutex);
auto it = mutexCache.find(key);
if (it == mutexCache.end())
{
it = mutexCache.emplace(key, std::make_unique<std::mutex>()).first;
}
inner_mutex = it->second.get();
}
{
std::lock_guard<std::mutex> c_lk(*inner_mutex);
return mainCache[key];
}
}发布于 2017-02-02 11:43:51
TL;DR:只是像std::map<std::string, std::mutex> map; map[filename];一样使用operator []
为什么首先需要使用std::unique_ptr?
当我必须创建一个std::map of std::mutex对象时,我也遇到了同样的问题。问题是std::mutex既不能复制也不能移动,所以我需要构建它“就位”。
我不能仅仅使用emplace,因为它不能直接用于缺省构造的值。有一个选项可以这样使用std::piecewise_construct:
map.emplace(std::piecewise_construct, std::make_tuple(key), std::make_tuple());但这是海事组织的复杂和可读性较差。
--我的解决方案要简单得多----只需使用operator[] --它将使用其默认构造函数创建值并返回对其的引用。或者,它只会找到并返回对已经存在的项的引用,而不会创建新的项。
std::map<std::string, std::mutex> map;
std::mutex& GetMutexForFile(const std::string& filename)
{
return map[filename]; // constructs it inside the map if doesn't exist
}发布于 2019-11-05 07:55:11
如果您可以访问c++17,您可以使用std::map::try_emplace而不是使用指针,对于不可复制和不可移动的类型,它应该工作得很好!
https://stackoverflow.com/questions/25544741
复制相似问题