首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >互斥c++11地图

互斥c++11地图
EN

Stack Overflow用户
提问于 2014-08-28 08:58:44
回答 4查看 11.1K关注 0票数 12

我需要建立一个线程安全的映射,我的意思是每个值必须是独立互斥的。例如,我需要能够同时从两个不同的线程获得map["abc"]map["vf"]

我的想法是制作两张地图:一张是数据,另一张是互斥键:

代码语言:javascript
复制
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;但是当我编译它时,我得到:

代码语言:javascript
复制
/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>);
                                                          ^

我该如何解决这个问题?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-08-28 09:01:20

mutexCache.insert(new std::unique_ptr<std::mutex>)替换为:

代码语言:javascript
复制
mutexCache.emplace(key, new std::mutex);

在C++14中,您应该说:

代码语言:javascript
复制
mutexCache.emplace(key, std::make_unique<std::mutex>());

但是,整个代码非常杂乱无章,不优雅。应该是这样的:

代码语言:javascript
复制
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];
    }
}
票数 14
EN

Stack Overflow用户

发布于 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

代码语言:javascript
复制
map.emplace(std::piecewise_construct, std::make_tuple(key), std::make_tuple());

但这是海事组织的复杂和可读性较差。

--我的解决方案要简单得多----只需使用operator[] --它将使用其默认构造函数创建值并返回对其的引用。或者,它只会找到并返回对已经存在的项的引用,而不会创建新的项。

代码语言:javascript
复制
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
}
票数 17
EN

Stack Overflow用户

发布于 2019-11-05 07:55:11

如果您可以访问c++17,您可以使用std::map::try_emplace而不是使用指针,对于不可复制和不可移动的类型,它应该工作得很好!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25544741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档