线程安全读取 class 成员向量而不复制

Thread safe read of a class member vector without copying

假设我有一个 class:

class A
{
   private:
   std::vector<MyObject> history;
   std::mutex historyLock;
}

有多个线程由 class 初始化,它们获取互斥锁并写入历史向量。假设我有另一个 class 我想在其中阅读该列表:

class B
{
   public:
   B(A instanceA) 
   {
      // I want to read the list here in a thread safe way
   }
}

我的直觉告诉我在 class A 中公开一个名为 GetHistory() 的方法,该方法将锁定互斥锁、复制列表和 return 副本。

有没有办法在不产生复制操作成本的情况下读取 class B 中的列表?

有多种方法可以解决此类问题。一种方法是使用更复杂的结构来存储您的历史记录,例如不可变向量。 (不可变向量以迭代性能换取廉价副本。)但仅使用标准 C++,我认为最简单的方法是将遍历成员函数模板添加到接受回调的 class A:

template <class F> void TraverseHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  for (auto const& item : history)
  {
    callback(item);
  }
}

如果您不想使用函数模板,也可以使用 std::function

void TraverseHistory(std::function<void(MyObject const&)> const& callback);

另一种选择是将对整个向量的引用传递给您的回调。使用这种方法,函数模板将如下所示:

template <class F> void ReadHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  callback(std::as_const(history));
}