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 auto handler = +[](int) {
31 if (
auto *s = solver_to_stop.load(std::memory_order::acquire))
32 reinterpret_cast<Solver *
>(s)->stop();
35 signal(SIGINT, handler);
36 signal(SIGTERM, handler);
38 struct sigaction action;
39 action.sa_handler = handler;
40 sigemptyset(&action.sa_mask);
42 sigaction(SIGINT, &action,
nullptr);
43 sigaction(SIGTERM, &action,
nullptr);
45 auto detach_solver = +[](solver_to_stop_t *p) {
47 signal(SIGINT, SIG_DFL);
48 signal(SIGTERM, SIG_DFL);
50 struct sigaction action;
51 action.sa_handler = SIG_DFL;
52 sigemptyset(&action.sa_mask);
54 sigaction(SIGINT, &action,
nullptr);
55 sigaction(SIGTERM, &action,
nullptr);
57 p->store(
nullptr, std::memory_order_relaxed);
59 std::atomic_signal_fence(std::memory_order_release);
61 return std::unique_ptr<solver_to_stop_t,
decltype(detach_solver)>{
62 &solver_to_stop, detach_solver};
64 struct [[maybe_unused]] empty {};