保留对tbb :: concurrent_unordered_map项目的参考安全吗?

Is it safe to hold references to tbb::concurrent_unordered_map items?

本文关键字:参考 安全 项目 unordered tbb concurrent 保留 map      更新时间:2023-10-16

我遇到了我继承的一些现有代码,并存储存储在tbb :: concurrent_unordered_map中的结构的引用。我知道它是否是一个迭代器,它将是安全的,但是对实际物体的参考似乎是腥的。

代码不断将新项目插入tbb :: concurrent_unordered_map。插入是否可以不更改TBB地图内包含的项目的物理位置,这会使存储的引用指向错误的位置,因为它会像STD :: MAP?

那样。

TBB文档指出:

"喜欢std :: list,插入新项目不会使任何内容无效 迭代器,也不更改地图中已经项目的顺序。插入 和遍历可能是并发的。"

我知道std ::列表列表时,插入新项目时的位置不会更改,而是因为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
};

此代码已经以相对较高的频率运行一年多,这似乎表明它是安全的:: concurrent_unordered_map。

重写代码很多工作,所以如果可以的话,我宁愿不必这样做。

谢谢,

Paul

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

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

这是因为除了指向元素的指针外,迭代器还具有指向其所属容器的指针。没有指针或任何其他结构列表,它们会记录所有迭代器用户创建的迭代器,因此容器无法更新插机以指向其他地址(在并行程序中尤其棘手(。无论如何,这样的搬迁会导致额外的用户可见呼叫,以移动/复制密钥/值类型的构造函数,因此会记录下来。文档中没有这样的警告,并添加它会导致向后不相容的更改,这为您提供了一种间接的保证,您可以安全地将指针保留到项目上而不是使用迭代器。