44#define GECODE_BLACKBOX_EXPORT __declspec(dllexport)
45#define GECODE_BLACKBOX_CALL __stdcall
50#if defined(__GNUC__) || defined(__clang__)
51#define GECODE_BLACKBOX_EXPORT __attribute__((visibility("default")))
53#define GECODE_BLACKBOX_EXPORT
55#define GECODE_BLACKBOX_CALL
60 enum class Mode { normal, nan };
64 const std::string log;
65 const unsigned int id;
67 Instance(
const char** args,
size_t n_args,
unsigned int id0)
68 : mode((n_args > 0) && (std::strcmp(args[0],
"nan") == 0)
69 ? Mode::nan : Mode::normal),
70 log((n_args > 1) ? args[1] :
""), id(id0) {}
71 Instance(
const Instance& other,
unsigned int id0)
72 : mode(other.mode), log(other.log), id(id0) {}
75 std::atomic<unsigned int> next_id(0);
79 return next_id.fetch_add(1, std::memory_order_relaxed) + 1;
83 record(
const std::string& log,
const std::string& event,
unsigned int id) {
87 const std::string line =
event +
" " + std::to_string(
id) +
"\n";
89 HANDLE file = CreateFileA(log.c_str(), FILE_APPEND_DATA,
90 FILE_SHARE_READ | FILE_SHARE_WRITE |
92 nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
94 if (file == INVALID_HANDLE_VALUE) {
98 (void)WriteFile(file, line.data(),
static_cast<DWORD
>(line.size()),
100 (void)CloseHandle(file);
104 fd = open(log.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0600);
105 }
while ((fd == -1) && (errno == EINTR));
111 n = write(fd, line.data(), line.size());
112 }
while ((n == -1) && (errno == EINTR));
118 has_two_starts(
const std::string& log) {
119 std::ifstream in(log.c_str());
120 std::set<unsigned int> ids;
123 while (in >> event >>
id) {
124 if (event ==
"start") {
128 return ids.size() >= 2;
132 wait_for_peer(
const std::string& log,
unsigned int id) {
133 for (
unsigned int i = 0; i < 500; ++i) {
134 if (has_two_starts(log)) {
143 record(log,
"timeout",
id);
150 Instance* instance =
new Instance(args, n_args, instance_id());
151 record(instance->log,
"init", instance->id);
157 Instance* instance =
new Instance(*
static_cast<Instance*
>(value),
159 record(instance->log,
"clone", instance->id);
165 Instance* instance =
static_cast<Instance*
>(value);
166 record(instance->log,
"free", instance->id);
172 const double* float_input,
size_t n_float_input,
173 int64_t* int_output,
size_t n_int_output,
174 double* float_output,
size_t n_float_output) {
175 const Instance* instance =
static_cast<const Instance*
>(value);
176 if (!instance->log.empty() && (n_int_input > 0)) {
177 record(instance->log,
"start", instance->id);
178 wait_for_peer(instance->log, instance->id);
179 record(instance->log,
"ready", instance->id);
181 for (
size_t i = 0; i < n_int_output; ++i) {
182 int_output[i] = (n_int_input == 0)
184 : int_input[i % n_int_input];
186 for (
size_t i = 0; i < n_float_output; ++i) {
187 if (instance->mode == Mode::nan) {
188 const uint64_t nan = UINT64_C(0x7ff8000000000000);
189 std::memcpy(&float_output[i], &nan,
sizeof(nan));
191 float_output[i] = (n_float_input == 0)
192 ? 0.0 : float_input[i % n_float_input];
#define GECODE_BLACKBOX_CALL
GECODE_BLACKBOX_EXPORT void GECODE_BLACKBOX_CALL fzn_free(void *value)
GECODE_BLACKBOX_EXPORT void *GECODE_BLACKBOX_CALL fzn_init(const char **args, size_t n_args)
GECODE_BLACKBOX_EXPORT void *GECODE_BLACKBOX_CALL fzn_clone(void *value)
#define GECODE_BLACKBOX_EXPORT
GECODE_BLACKBOX_EXPORT void GECODE_BLACKBOX_CALL fzn_blackbox(void *value, const int64_t *int_input, size_t n_int_input, const double *float_input, size_t n_float_input, int64_t *int_output, size_t n_int_output, double *float_output, size_t n_float_output)