Как использовать shared_mutex для объектов в элементах std :: vector - PullRequest
0 голосов
/ 21 января 2019

Проблема

Я сейчас работаю над игрой.В этой игре «игровые объекты» определенного типа хранятся в std :: vector.Код обновления (геймплея) для этих объектов выполняется в одном потоке, а рендеринг обрабатывается основным потоком.

Вектор этих "игровых объектов" передается по ссылке на поток, обрабатывающий их код обновления,так что данные распределяются между потоками.Таким образом, требуется некоторая форма безопасности потоков, чтобы предотвратить попытки кода рендеринга получить доступ к памяти, которая модифицируется кодом обновления (который вызывает сбой).

В идеале я хотел бы использоватьshared_mutex как часть этих «игровых объектов», хранящихся в указанном векторе.Тем не менее, это не скомпилируется и вызывает ошибки.Насколько я понимаю, это потому, что мьютекс не может быть скопирован.

Есть ли способ решить эту проблему, который является производительным, безопасным и "не кошмарным для работы"?

Единственное жизнеспособное решение, которое я вижу, - это предотвращение обновления и рендеринга каждого конкретного типа объекта одновременно.Однако это могло бы свести на нет преимущества многопоточности.Я предполагаю, что более 80% игр будут обрабатывать один тип объекта.

Базовый Psuedocode для обеспечения контекста ниже:

main(){

   std::vector<Enemies> enemies;

   std::thread(update_thread, std::ref(enemies), ... , ...);

   while(true){
      render_player();
      render_enemies();
      render_physics();

      flip_to_display()
   }
};
update_thread(std::vector<Enemies> &enemies, ... , ...){
   while(true){
      update_player();
      update_enemies();
      update_physics();
   }
};
render_enemies(){
   for(all enemies)
      enemy.render();
}
update_enemies(){
   for(all enemies)
      enemy.update();
}
class Enemies{
   //Would be nice to have the below, but afaik, not possible
   std::shared_mutex mutex;

   update(){
      std::shared_lock<std::shared_mutex> lock(mutex);

      //Write and Access data from enemy
   }

   render(){
      std::shared_lock<std::shared_mutex> lock_shared(mutex);

      //Only Access some data from enemy and draw it
   }
}

ПРИМЕЧАНИЕ. Я использую Visual Studio 2015, поэтому я могу использовать только функции, совместимые с C ++ 14 (ish).

1 Ответ

0 голосов
/ 21 января 2019

Основываясь на ответах, предоставленных в комментариях, я думаю, что мой лучший вариант - найти более креативное решение, которое полностью обойдет проблему. В этом случае я, вероятно, обработаю заранее и запишу результаты в буфер. Таким образом, рендеринг и обработка должны по замыслу избегать любых конфликтов, следовательно, избегать необходимости в условиях блокировки.

При условии, что я помню, это, скорее всего, станет принятым решением (поскольку кнопка не может быть нажата в течение 2 дней).

...