20template <
class Solver>
23 using solver_to_stop_t =
decltype(solver_to_stop);
24 if constexpr (
requires { solver.stop(); }) {
25 auto *old = solver_to_stop.exchange(&solver, std::memory_order_release);
27 throw std::logic_error(
28 "alpaqa-driver:attach_cancellation can only be used once");
30 struct sigaction action;
31 action.sa_handler = [](int) {
32 if (
auto *s = solver_to_stop.load(std::memory_order::acquire))
33 reinterpret_cast<Solver *
>(s)->stop();
35 sigemptyset(&action.sa_mask);
37 sigaction(SIGINT, &action,
nullptr);
38 sigaction(SIGTERM, &action,
nullptr);
39 auto detach_solver = +[](solver_to_stop_t *p) {
40 struct sigaction action;
41 action.sa_handler = SIG_DFL;
42 sigemptyset(&action.sa_mask);
44 sigaction(SIGINT, &action,
nullptr);
45 sigaction(SIGTERM, &action,
nullptr);
46 p->store(
nullptr, std::memory_order_relaxed);
48 return std::unique_ptr<solver_to_stop_t,
decltype(detach_solver)>{
49 &solver_to_stop, detach_solver};
51 struct [[maybe_unused]] empty {};
std::atomic< void * > solver_to_stop
auto attach_cancellation(Solver &solver)
Attach SIGINT and SIGTERM handlers to stop the given solver.