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.