summaryrefslogtreecommitdiffhomepage
path: root/ProcessRunner.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2024-05-03 21:03:06 +0200
committerRoland Reichwein <mail@reichwein.it>2024-05-03 21:03:06 +0200
commit45983abe664be648b513202c8c12578c9a85784f (patch)
tree37166e1f24219b84aab1c9e79d7743c8f59e9022 /ProcessRunner.cpp
parent6669794434cb9f472aafce126162b9b81389df5f (diff)
Parallel build
Diffstat (limited to 'ProcessRunner.cpp')
-rw-r--r--ProcessRunner.cpp92
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();
+}
+