0

I have a long computation in a loop, which I need to end prematurely if allowed compute time expires (and return a partially computed result). I plan to do it via SIGALARM handler and a timer:

// Alarm handler will set it to true.
bool expired = false;

int compute ()
{
    int result;

    // Computation loop:
    for (...) {
        // Computation here.

        if (expired)
            break;
    }
    return result;
}

My question is: how to correctly define the expired variable (volatile bool or std::atomic<bool>, or std::sig_atomic_t, etc), how to set it true in the signal handler (just an assignment or atomic operation), and how to check its value in the compute function?

This is a single-threaded C++17 code...

user2052436
  • 4,321
  • 1
  • 25
  • 46
  • [this answer](https://stackoverflow.com/questions/56598970/stdatomicint-memory-order-relaxed-vs-volatile-sig-atomic-t-in-a-multithreade/56600194#56600194) is related – LWimsey Jan 21 '22 at 12:09

2 Answers2

0

If you aren't using multiple threads, you don't need an atomic operation. Just set the global variable expired = true in the signal handler.

EDIT: as @Frank demonstrated below, the compiler might optimize it out. You can avoid this by declaring expired as volatile bool expired = false;

user16978892
  • 150
  • 1
  • 7
  • The check can end up being hoisted out of the loop. That's exactly what gcc does: https://gcc.godbolt.org/z/fYYvjs34d –  Jan 20 '22 at 15:27
  • A signal handler is just a regular function from the POV of the compiler. If you change the value of a global variable in a function within the same program, why would the compiler eliminate it? – user16978892 Jan 20 '22 at 15:30
  • 2
    Because the compiler doesn't see that function being called from within the loop, so it's allowed to assume that it never get called from there. If the compiler does not see anything that can directly or indirectly modify `expired` inside the loop, it can assume that whatever value it had at the start of the loop will always be the one for every iteration. –  Jan 20 '22 at 15:31
  • Technically it ought to be `volatile sig_atomic_t` instead of `volatile bool`, though in practice I'd expect actual systems to do just fine with `volatile bool`. – Nate Eldredge Jan 22 '22 at 05:30
  • Indeed, as Frank said, even though your signal handler is a regular function, the compiler assumes it only gets called when you call it synchronously. If asynchronous execution is possible, it's on you to use things like `volatile` to make sure the optimizer takes it into account. If the compiler had to assume that any function in the program could be called asynchronously at any time, a huge number of valuable optimizations would be forbidden. – Nate Eldredge Jan 22 '22 at 05:32
0

Unless one iteration takes a considerable amount of time, I would suggest that you don't bother with signals and simply check the gettimeofday at each iteration.

mmomtchev
  • 2,497
  • 1
  • 8
  • 23