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;
}