0

Is it safe to have a variable passed by const reference modified externally (via an interrupt)?

std::atomic_bool g(true);

void sig_handler(int num) {
   switch(num) {
      case SIGHUP:
        g = false;
        break;
   }
}

void method(const std::atomic_bool &flag) {

   while(flag) {
      ...
   }
}

method(g);  // blocks

Here we have a const reference that is modified externally via an interrupt. I get the fact that the callee (method) can't modify flag, but can the caller modify g? Because in g space std::atomic_bool is not const.

ascotan
  • 1,634
  • 11
  • 8

2 Answers2

2

If this is an external process / OS that's changing the flag, then you just need atomic, that's all, no volatile needed. This is the case for SIGHUP.

If this is an actual hardware interrupt that changes the value: this is one of the very few valid use cases of volatile keyword. (Very) loosely speaking, volatile informs the compiler that it cannot assume that the value written to an address last will be the value read from the address, or that the value doesn't change without writing into it. In this case, you have a const volatile std::atomic_bool& - in this case, declare g itself as both volatile and atomic.

lorro
  • 10,687
  • 23
  • 36
0

I don't agree with @lorro here. You don't really need volatile modifier.

std::atomic<T>::operator<T> :

Atomically loads and returns the current value of the atomic variable. Equivalent to load().

It means that each time your evaluate flag in loop condition you atomically obtain actual value of flag variable. And you don't have to flag this variable as volatile.

Difference between volatile and std::atomic types is perfectly explained in Scott Meyers Effective Modern C++, chapter Item 40: Use std::atomic for concurrency, volatile for special memory.

  • You don't have to agree :), but how is it not special memory when an interrupt directly modifies the memory value? Your comment is valid if a concurrent task - like, interrupt-triggered event that lets a task continue and then write - modifies the value. When a memory address is modified externally, by hardware, then why wouldn't it be specific memory? Not claiming it as best source, but MSDN defines volatile as: 'A type qualifier that you can use to declare that an object can be modified in the program by the hardware.' Also: http://stackoverflow.com/questions/72552/why-does-volatile-exist – lorro Jul 10 '16 at 14:43
  • @lorro, about what hardware interrupt are you talking? Topic starter example consider UNIX signal interrupt which has nothing in common with hardware interrupts. Variable g is modified by code from the same processor but on different stack/CPU context. volatile is definitely not a case here. –  Jul 10 '16 at 20:47
  • @user1631854: OP writes 'modified externally (via an interrupt)', but then gives an example that has SIGHUP. These are contradicting. The former needs `volatile`, the latter needs just atomic. Editing my post to make this clear. – lorro Jul 10 '16 at 21:08