#include "ProcessRunner.h" #include #include #include #include namespace bp = boost::process; ProcessRunner::ProcessRunner(): _max_number_of_processes{static_cast(std::thread::hardware_concurrency())} {} void ProcessRunner::spawn(const std::string& key, const std::string& command) { _processes.emplace_back(process{key, command}); } bool ProcessRunner::empty() { return running() == 0; } bool ProcessRunner::full() { return running() == _max_number_of_processes; } int ProcessRunner::wait_one(std::string& key) { if (running() > 0 && finished() == 0) { waitpid(-1, NULL, 0); } // Actually, several childs may have finished. Therefore, end and // remove all finished childs. if (finished() > 0) { for (auto it = _processes.begin(); it != _processes.end(); ++it) { bp::child &child{it->child}; if (!child.running()) { child.wait(); int result{child.exit_code()}; key = it->key; _processes.erase(it, it+1); return result; } } }; if (_processes.empty()) { throw std::runtime_error("No process to wait for"); } throw std::runtime_error("No process finished"); } int ProcessRunner::wait_all() { int ret{}; for (auto &i: _processes) { i.child.wait(); int result{i.child.exit_code()}; if (result != 0 && ret == 0) { ret = result; } } _processes.clear(); return ret; } size_t ProcessRunner::running() { size_t result{}; for (auto &i: _processes) { if (i.child.running()) { ++result; } } return result; } size_t ProcessRunner::finished() { return _processes.size() - running(); }