diff options
Diffstat (limited to 'ProcessRunner.cpp')
-rw-r--r-- | ProcessRunner.cpp | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/ProcessRunner.cpp b/ProcessRunner.cpp new file mode 100644 index 0000000..bdde054 --- /dev/null +++ b/ProcessRunner.cpp @@ -0,0 +1,92 @@ +#include "ProcessRunner.h" + +#include <stdexcept> +#include <thread> + +#include <boost/process.hpp> + +#include <sys/wait.h> + +namespace bp = boost::process; + +ProcessRunner::ProcessRunner(): + _max_number_of_processes{static_cast<int>(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(); +} + |