保留对tbb :: concurrent_unordered_map项的引用是否安全?

时间:2019-05-09 14:13:59

标签: c++ tbb

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

代码不断将新项目插入tbb :: concurrent_unordered_map中。插入是否可以更改tbb映射中包含的项目的物理位置,从而使存储的引用指向与std :: map相同的错误位置?

tbb文档指出:

  

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

对于std :: list,我知道插入新项目时位置不会改变,但是因为currently_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。

重写代码需要大量工作,因此,如果可以保留原样,我宁愿不必这样做。

谢谢

保罗

1 个答案:

答案 0 :(得分:0)

如果您非常担心进入未完全记录的行为的灰色区域,为什么不存储和使用迭代器呢?问题之一是它的大小(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。没有指针或任何其他结构的列表,这些列表注册了用户创建的所有迭代器,因此容器无法更新插入器以指向不同的地址(在并行程序中尤其棘手)。无论如何,这样的重定位将引起用户对键/值类型的移动/复制构造函数的其他可见调用,因此将被记录在案。文档中没有这样的警告,添加警告会导致向后不兼容的更改,这为您提供了一种间接保证,您可以安全地保留指向项目的指针,而不使用迭代器。