【问题标题】:Is it safe to hold references to tbb::concurrent_unordered_map items?保存对 tbb::concurrent_unordered_map 项目的引用是否安全?
【发布时间】:2019-05-09 14:13:59
【问题描述】:

我遇到了一些我继承的现有代码,它查找并存储存储在 tbb::concurrent_unordered_map 中的结构的引用。我知道如果它是一个迭代器,它会是安全的,但是对实际对象的引用似乎很可疑。

代码不断将新项目插入 tbb::concurrent_unordered_map。插入是否可以不更改 tbb 映射中包含的项目的物理位置,这会使存储的引用指向错误的位置,就像 std::map 一样?

tbb 文档指出:

"与 std::list 一样,插入新项不会使任何项无效 迭代器,也不会更改地图中已有项目的顺序。插入 并且遍历可能是并发的。”

我知道对于 std::list,插入新项目时位置不会改变,但因为 concurrent_unordered_map 文档只讨论了订单,我担心这并没有明确说明它可以移动位置。

下面是一些伪代码,演示了我遇到的代码的概念。

struct MyStruct {
    int i;
    int j;
};

//some other thread will insert items into myMap
tbb::concurrent_unordered_map <int, MyStruct> myMap;

MyStruct& getMyStruct (int id)
{
    auto itr=myMap.find (id);
    if (itr!=myMap.end ()) return itr->second;

    static MyStruct dummy {1,2};
    return dummy;
}


class MyClass {
public:
    MyClass (int id)
            :m_myStruct {getMyStruct (id)}
    {

    }

    void DoSomething () {
        std::cout<<m_myStruct.i<<std::endl;
    }
protected:
    MyStruct& m_myStruct; //reference to an item held into a tbb::concurrent_unordered_map
};

这段代码已经以相对较高的频率运行了一年多,这似乎表明它是安全的,但我想确定保留对 tbb 中包含的项目的引用是安全的::concurrent_unordered_map。

重写代码需要做很多工作,所以如果可以保持原样,我宁愿不必这样做。

谢谢,

保罗

【问题讨论】:

    标签: c++ tbb


    【解决方案1】:

    如果您非常担心进入没有完全记录的行为的灰色区域,为什么不存储和使用迭代器呢?一个问题是它的大小(run it):

    #include <tbb/tbb.h>
    
    int main() {
        tbb::concurrent_unordered_map<int, int> m;
        printf("Size of iterator: %lu\n", sizeof(m.begin()));
    }
    

    这是因为除了pointer to the element,迭代器还有它所属的pointer to the container。没有指针列表或任何其他结构来注册用户创建的所有迭代器,因此容器无法更新迭代器以指向不同的地址(这在并行程序中尤其棘手)。无论如何,这样的重定位会导致额外的用户可见调用键/值类型的移动/复制构造函数,因此将被记录。文档中没有这样的警告,添加它会导致向后不兼容的更改,这为您提供了一种间接保证,即您可以安全地保留指向项目的指针而不是使用迭代器。

    【讨论】:

      猜你喜欢
      • 2018-06-08
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-02
      • 1970-01-01
      • 2011-11-25
      相关资源
      最近更新 更多