inline std::vector simulateWithProcesses()

in src/simulator/benchmark_box2d.cpp [171:236]


inline std::vector<Scene> simulateWithProcesses(
    const std::vector<Scene>& scenes, const int num_steps,
    const size_t num_workers) {
  std::vector<int> pids;

  // Assume that the sizes of scenes are not changes during simulation.
  std::vector<uint8_t*> sceneSharedBuffers;
  std::vector<size_t> bufferSizes;
  for (const auto& scene : scenes) {
    const size_t sz = serialize(scene).size();
    bufferSizes.push_back(sz);
    sceneSharedBuffers.push_back(static_cast<uint8_t*>(sharedMalloc(sz)));
  }

  std::cout << "Using " << num_workers << " processes" << std::endl;
  for (size_t i = 0; i < num_workers; ++i) {
    const int pid = fork();
    if (pid == 0) {
      // Child.
      for (size_t j = i; j < scenes.size(); j += num_workers) {
        const Scene newScene = simulate(scenes[j], num_steps);
        const std::vector<uint8_t> serializedNewScene = serialize(newScene);
        if (serializedNewScene.size() != bufferSizes[j]) {
          exit(3);
        }
        std::copy_n(serializedNewScene.data(), serializedNewScene.size(),
                    sceneSharedBuffers[j]);
      }
      exit(0);
    } else if (pid < 0) {
      // Error.
      std::cout << "FATAL: Fork failed!" << std::endl;
      exit(2);
    } else {
      // Parent.
      pids.push_back(pid);
    }
  }
  for (const int pid : pids) {
    int status;
    if (waitpid(pid, &status, 0) != -1) {
      if (WIFEXITED(status)) {
        int returned = WEXITSTATUS(status);
        if (returned != 0) {
          std::cout << "FATAL: Worker exited with failure status: " << returned
                    << std::endl;
          exit(5);
        }
      } else {
        std::cout << "FATAL: Worker died unexpectedly" << std::endl;
        exit(5);
      }
    } else {
      std::perror("FATAL: waitpid() failed");
      exit(5);
    }
  }
  std::vector<Scene> newScenes(scenes.size());
  for (size_t i = 0; i < newScenes.size(); ++i) {
    std::vector<uint8_t> serialized(sceneSharedBuffers[i],
                                    sceneSharedBuffers[i] + bufferSizes[i]);
    newScenes[i] = deserialize(serialized);
    sharedFree(sceneSharedBuffers[i], bufferSizes[i]);
  }
  return newScenes;
}