Заполнение вектора unique_ptr несколькими потоками? - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть класс, который, учитывая идентификатор устройства, инициализирует это устройство. Деструктор класса снова подменяет устройство.

Поскольку к моей системе подключено несколько таких устройств, я написал класс перечислителя, который инициализирует каждое подключенное устройство. Поскольку деструктор device высвобождает ресурсы устройства, я использовал unique_ptr< device >, поэтому не происходит непреднамеренного копирования / удаления device объектов.

struct device_id {
    // information to identify device
}

class device {
    public:
        device( device_id const & id ) {
            // initialize device
        }

        void act() {
            // use the device
        }

        ~device() {
            // spool down device
        }
};

class device_enumerator {
    public:
        device_enumerator( std::vector< device_id > const & ids ) {
            for ( auto const & id : ids ) {
                devices.push_back( std::unique_ptr< device >( new device( id ) ) );
            }
        }

        typedef std::vector< std::unique_ptr< device > > device_vector;

        device_vector::iterator begin() { return devices.begin(); }
        device_vector::iterator end() { return devices.end(); }

    private:
        device_vector devices;
};

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

Но - это первый раз, когда я пытаюсь работать с <thread> - я не могу обернуться, пытаясь найти std::unique_ptr< device > из std::thread для каждого устройства, а затем присоединиться к опять темы, с любой элегантностью. (Если std::thread действительно правильно использовать здесь ...)

Как я могу распараллелить это:

for ( auto const & id : ids ) {
    devices.push_back( std::unique_ptr< device >( new device( id ) ) );
}

1 Ответ

0 голосов
/ 30 апреля 2018

Поскольку инициализация каждого устройства является независимой задачей, то здесь std :: async имеет больше смысла, и пример кода для этого выглядит следующим образом:

void init(std::unique_ptr<device>& p)
{
  p.reset(new device(device_id())); //time consuming operation

}
int main() {
  //8 number of elements in vector are for demo purpose only
  std::vector<std::unique_ptr<device>> vecOfDevices(8); 
  std::vector<std::future<void>> vecOfFutures(8);
  int index = 0;
  for(auto& elem:vecOfDevices)
  {
    //async launch policy will construct each in seperate thread
    vecOfFutures[index] = std::async(std::launch::async,init,std::ref(vecOfDevices[index]));
    index++;
  }
  //Do some other operations here
  for(auto& elem:vecOfFutures)
  {
    elem.wait(); //wait so that all devices got initialized
  }
  //start using your devices from here
  vecOfDevices[0]->act();  
  return 0;
}
...