代码之家  ›  专栏  ›  技术社区  ›  Damir Tenishev

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

  •  -1
  • Damir Tenishev  · 技术社区  · 1 年前

    MS Concurrency::concurrent_unordered_map 不提供 emplace 方法,所以我没有机会使用的建议 How to store std::atomic in a structure as a value in 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的值必须被构造 安置就位 .

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

    另一种选择是使用 oneapi::tbb::concurrent_unordered_map 它提供 安置就位 并且是可移植的,但如果有机会用MS的现有容器解决这个问题,我还没有准备好添加另一个库。

    1 回复  |  直到 1 年前
        1
  •  2
  •   Pepijn Kramer    1 年前

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

    演示: 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}});
    }