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

120 lines
2.4 KiB
C++

#include "tests.hpp"
#include "thespian/env.hpp"
#include "thespian/handle.hpp"
#include <thespian/instance.hpp>
using std::move;
using thespian::behaviour;
using thespian::context;
using thespian::env;
using thespian::env_t;
using thespian::exit;
using thespian::exit_handler;
using thespian::ok;
using thespian::receive;
using thespian::result;
using thespian::self;
using thespian::spawn;
using thespian::spawn_link;
using thespian::to_result;
using thespian::trap;
using thespian::unexpected;
namespace {
auto initE() {
check(env().str("initAsays") == "yes");
check(env().str("initBsays") == "");
check(env().str("initCsays") == "no");
check(env().num("intval") == 42);
check(!env().proc("A").expired());
link(env().proc("A"));
auto ret = env().proc("A").send("shutdown");
if (not ret)
return ret;
receive([](auto, auto) { return ok(); });
return ok();
}
auto initD() {
auto ret = spawn(initE, "E");
if (not ret)
return to_result(ret);
receive([](auto, auto m) {
if (m("die"))
return exit("died");
return unexpected(m);
});
return ok();
}
auto initC() {
env().str("initCsays") = "no";
auto ret = spawn_link(initD, "D").value().send("die");
if (not ret)
return to_result(ret);
trap(true);
receive([](auto /*from*/, auto m) {
if (m("exit", "died"))
return exit();
return unexpected(m);
});
return ok();
}
auto initB() {
env().str("initBsays") = "noyoudont";
receive([](auto from, auto m) {
if (m("shutdown")) {
auto ret = from.send("done");
if (not ret)
return ret;
return exit();
}
return unexpected(m);
});
return ok();
}
auto initA() {
link(env().proc("log"));
env().str("initAsays") = "yes";
env().num("intval") = 42;
env().proc("A") = self();
auto ret = spawn_link(initB, "B").value().send("shutdown");
if (not ret)
return ret;
spawn_link(initC, "C").value();
receive([i{0}](auto, auto m) mutable {
if (m("shutdown") || m("done"))
++i;
else
return unexpected(m);
if (i == 2)
return exit("done");
return ok();
});
return ok();
}
} // namespace
auto spawn_exit(context &ctx, bool &result, env_t env) -> ::result {
behaviour b;
check(!b);
b = []() { return ok(); };
check(!!b);
b = behaviour{};
check(!b);
return to_result(ctx.spawn_link(
initA,
[&](auto s) {
if (s == "done")
result = true;
},
"spawn_exit", move(env)));
}