56 return std::to_string(
static_cast<int64_t
>(GetCurrentProcessId()));
58 return std::to_string(
static_cast<int64_t
>(getpid()));
63 record(
const std::string& log,
const std::string& event,
64 const std::string&
id) {
68 const std::string line =
event +
" " +
id +
"\n";
70 HANDLE file = CreateFileA(
log.c_str(), FILE_APPEND_DATA,
71 FILE_SHARE_READ | FILE_SHARE_WRITE |
73 nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
75 if (file == INVALID_HANDLE_VALUE) {
79 (void)WriteFile(file, line.data(),
static_cast<DWORD
>(line.size()),
81 (void)CloseHandle(file);
85 fd = open(
log.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0600);
86 }
while ((fd == -1) && (errno == EINTR));
92 n = write(fd, line.data(), line.size());
93 }
while ((n == -1) && (errno == EINTR));
99 has_two_starts(
const std::string& log) {
100 std::ifstream in(
log.c_str());
101 std::set<std::string> ids;
104 while (in >> event >>
id) {
105 if (event ==
"start") {
109 return ids.size() >= 2;
113 wait_for_peer(
const std::string& log,
const std::string&
id) {
114 for (
unsigned int i = 0;
i < 500; ++
i) {
115 if (has_two_starts(log)) {
124 record(log,
"timeout",
id);
128 first_integer(
const std::string& request, int64_t& value) {
129 const std::string::size_type end = request.find(
';');
130 if ((end == std::string::npos) || (end == 0)) {
133 const std::string integer = request.substr(0, end);
134 char* last =
nullptr;
136 const long long parsed = std::strtoll(integer.c_str(), &last, 10);
137 if ((last == integer.c_str()) || (*last !=
'\0') || (errno == ERANGE) ||
138 (parsed < (std::numeric_limits<int64_t>::min)()) ||
139 (parsed > (std::numeric_limits<int64_t>::max)())) {
142 value =
static_cast<int64_t
>(parsed);
147 write_response(
const std::string& value) {
148 std::cout.write(value.data(),
static_cast<std::streamsize
>(value.size()));
149 std::cout << std::endl;
154 dependent_bounds(
const std::string& request) {
155 long long xmin, xmax, ymin, ymax;
156 if (std::sscanf(request.c_str(),
"%lld,%lld,%lld,%lld;",
157 &xmin, &xmax, &ymin, &ymax) != 4) {
162 write_response(std::to_string(xmin) +
"," + std::to_string(xmax) +
"," +
163 std::to_string(5 * xmin) +
"," +
164 std::to_string(5 * xmax) +
";");
169 fixed_response(
const std::string& mode) {
170 static const std::string value7(
"7;");
171 static const std::string bounds2(
"5,5;");
172 static const std::string bounds4(
"5,5,5,5;");
173 static const std::string mixed(
"5,5;5,5");
174 static const std::string nan(
";nan");
175 static const std::string nul(
";\0x", 3);
176 static const std::string malformed(
"x;");
177 if (mode ==
"value7") {
179 }
else if (mode ==
"bounds2") {
181 }
else if (mode ==
"bounds4") {
183 }
else if (mode ==
"mixed") {
185 }
else if (mode ==
"nan") {
187 }
else if (mode ==
"nul") {
189 }
else if (mode ==
"malformed") {
196 fault(int64_t kind) {
198 write_response(
"invalid");
199 }
else if (kind == 2) {
201 }
else if (kind == 3) {
202 write_response(std::string(
";\0x", 3));
203 }
else if (kind == 5) {
204 write_response(std::to_string((std::numeric_limits<int64_t>::max)()) +
207 write_response(std::string(1024U * 1024U + 1U,
'x'));
215 const std::string mode = (argc > 1) ? argv[1] :
"normal";
216 const std::string log = (argc > 2) ? argv[2] :
"";
217 unsigned int round = 0;
219 bool descendant_started =
false;
222 while (std::getline(std::cin, request)) {
225 const bool has_value = first_integer(request, value);
226 if (mode ==
"fault") {
227 fault(has_value ? value : 1);
230 if (mode ==
"descendant") {
232 if (!descendant_started) {
234 if (pipe(ready) != 0) {
237 const pid_t descendant = fork();
238 if (descendant == 0) {
239 (void)close(ready[0]);
240 record(log,
"descendant", process_id());
241 const char started =
'1';
242 (void)write(ready[1], &started, 1);
243 (void)close(ready[1]);
248 (void)close(ready[1]);
249 if (descendant <= 0) {
250 (void)close(ready[0]);
256 n = read(ready[0], &started, 1);
257 }
while ((n == -1) && (errno == EINTR));
258 (void)close(ready[0]);
259 if ((n != 1) || (started !=
'1')) {
262 descendant_started =
true;
265 write_response(
"1;");
269 if (mode ==
"dependent_bounds") {
270 if (!dependent_bounds(request)) {
276 if (
const std::string* value = fixed_response(mode)) {
277 write_response(*value);
281 if (!log.empty() && has_value) {
282 const std::string
id = process_id();
283 record(log,
"start",
id);
284 wait_for_peer(log,
id);
285 record(log,
"ready",
id);
287 write_response(std::to_string(has_value ? value :
288 static_cast<int64_t
>(round)) +
";");
int main(int argc, char *argv[])
void log(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Gecode::IntArgs i({1, 2, 3, 4})