有没有办法将 std::atomic 作为 MS Concurrency::concurrent_unordered_map 中的值存储在结构中?

问题描述 投票:0回答:1

MS Concurrency::concurrent_unordered_map不提供

emplace
方法,所以我没有机会使用如何将 std::atomic 在结构中存储为 std::unordered_map 中的值的建议?.

有机会让这个code编译吗?

#include <atomic>
#include <string>
#include <concurrent_unordered_map.h>

struct LexemData {
    unsigned int id{};
    std::atomic<size_t> counter{};
};

int main()
{
    Concurrency::concurrent_unordered_map<std::string, LexemData> dict;

    std::string lexem("lexem");
    
    dict.insert({ lexem, LexemData {0,0} });  // Doesn't compile
}

它不会编译并显示非常详细的错误消息,这很难在这里复制,但原因很简单,LexemData无法复制,因为它包含

std::atomic
并且必须构造map的值
emplace

我需要从多个线程增加这个计数器。

另一个选择是使用 oneapi::tbb::concurrent_unordered_map ,它提供

emplace
并且是可移植的,但如果有机会用 MS 的现有容器解决这个问题,我还没有准备好添加另一个库。

c++ std
1个回答
0
投票

是的,您应该在结构上实现以下构造函数。 最重要的是原子是不可移动的,所以你需要复制

演示:https://godbolt.org/z/hh65aE1TY

#include <atomic>
#include <string>
#include <concurrent_unordered_map.h>

struct LexemData final
{
    LexemData(unsigned int i, std::size_t count) :
        id{i},
        counter{count}
    {
    }

    LexemData(const LexemData& rhs) :
        id { rhs.id },
        counter {rhs.counter.load() }
    {
    }

    LexemData& operator=(const LexemData& rhs)
    {
        if ( &rhs != this)
        {
            id = rhs.id;
            counter = rhs.counter.load();
        }
    }

    LexemData(LexemData&&) = delete;  // atomic is not moveable
    LexemData& operator=(LexemData&&) = delete;

    ~LexemData() = default;

    unsigned int id;
    std::atomic<std::size_t> counter;
}; 

int main()
{
    Concurrency::concurrent_unordered_map<std::string, LexemData> dict;
    dict.insert({"lexem",{0u,0}});
}
© www.soinside.com 2019 - 2024. All rights reserved.