blob: bdde0542105c1469958525ac2aa906db95ab3101 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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();
}
|