Потоковое чтение вектора члена класса без копирования - PullRequest
0 голосов
/ 27 ноября 2018

Предположим, у меня есть класс:

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

Есть несколько потоков, инициализированных этим классом, которые получают мьютекс и записывают в вектор истории.Предположим, что у меня есть еще один класс, где я хочу прочитать этот список:

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

Моя интуиция подсказывает мне выставить метод в class A с именем GetHistory(), который блокирует мьютекс, копирует список ивернуть копию.

Есть ли способ прочитать список в классе B, не неся при этом затрат на операцию копирования?

1 Ответ

0 голосов
/ 27 ноября 2018

Есть несколько способов решения этой проблемы.Один из способов - использовать более сложную структуру для хранения вашей истории, например, неизменный вектор.(Неизменяемый вектор торгует производительностью итерации для дешевых копий.) Но, используя только стандартный C ++, я думаю, что самый простой способ - добавить шаблон функции-члена обхода к классу 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));
}
...