thespian/test/perf_spawn.cpp
2024-02-08 23:04:55 +01:00

73 lines
1.8 KiB
C++

#include "tests.hpp"
#include "thespian/env.hpp"
#include <thespian/instance.hpp>
#include <string>
using cbor::extract;
using std::move;
using thespian::context;
using thespian::env;
using thespian::env_t;
using thespian::exit;
using thespian::link;
using thespian::ok;
using thespian::receive;
using thespian::result;
using thespian::spawn_link;
using thespian::unexpected;
namespace {
auto slave(const int slaves, int spawned) -> result {
receive([slaves, spawned](auto, auto m) mutable {
int n{0};
if (!m(extract(n)))
return unexpected(m);
if (n) {
++spawned;
return thespian::to_result(
spawn_link([=]() { return slave(slaves, spawned); }, "slave")
.value()
.send(n - 1));
}
if (spawned != slaves) {
auto _ = env().proc("log").send("spawned", spawned, "slaves !=", slaves);
return exit("failed");
}
if (env().is("verbose"))
auto _ = env().proc("log").send("spawned", slaves, "slaves");
return exit("done");
});
return ok();
}
auto controller(const int slaves) -> result {
auto ret = spawn_link([=]() { return slave(slaves, 1); }, "slave");
if (not ret)
return to_result(ret);
auto ret2 = ret.value().send(slaves - 1);
if (not ret2)
return ret2;
receive([](auto, auto) { return exit(); });
return ok();
}
} // namespace
auto perf_spawn(context &ctx, bool &result, env_t env_) -> ::result {
auto slaves{env_.is("long_run") ? 1000000 : 1000};
return to_result((ctx.spawn_link(
[=]() {
link(env().proc("log"));
return controller(slaves);
},
[&](auto s) {
if (s == "done") {
result = true;
} else {
auto _ = env_.proc("log").send(s);
}
},
"perf_spawn", move(env_))));
}