9 ms·
For 1) lock-free atomics are also allowed. In C++ there's actually a lot more freedom. You can access non-atomic non-volatile-std :: sig_atomic_t variables as
by bigcheesegs 3y ago
For 1) lock-free atomics are also allowed.
In C++ there's actually a lot more freedom. You can access non-atomic non-volatile-std :: sig_atomic_t variables as long as you don't violate the data race rules.
- gpderetta 3y agoyou mean that sig_atomic_t is implicitly volatile in C++, regarding synchronization with signal handlers? I don't think that's the case.
- jlokier 3y ago> In C++ there's actually a lot more freedom. Not really. The two languages are similar on this. The 'volatile' before 'sig_atomic_t' is still required in C++ for the same reasons as C. You can access non-volatile sig_atomic_t variables in C too, but in both languages that's not enough for the signalling that type exists for, so you have to use 'volatile sig_atomic_t', in C and C++. An example of scenario 1) is the loop below. The 'volatile' is required in C++ the same as in C. If you interrupt the loop below in C++ with a signal handler that updates 'flag', the loop is not guaranteed to exit unless 'flag' is declared volatile. You can test this easily. Just now I compiled the C++ code below with Clang/LLVM with -O on a Mac, and GCC with -O on Linux. On both systems and compilers, Control-C fails to stop the process if 'volatile' is not used. If compiled without -O, Control-C always interrupts the process, but you can't rely on behaviour of disabled optimisations. #include <signal.h> #if 0 volatile #endif sig_atomic_t flag = 0; void handler(int sig) { flag = 1; } int main(void) { signal(SIGINT, handler); while (!flag) { /* Spin waiting for flag */ } return 0; }
- bigcheesegs 3y agoIn C++ this violates the data race rules both with and without volatile, but because it's sig_atomic_t it has a special carve out _only_ if it's volatile. See https://eel.is/c++draft/basic#intro.races-22 https://eel.is/c++draft/basic#intro.races-22 C however states : > When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects that are neither lock-free atomic objects nor of type volatile sig_atomic_t are unspecified, [...] The representation of any object modified by the handler that is neither a lock-free atomic object nor of type volatile sig_atomic_t becomes indeterminate when the handler exits. This wording is not present in C++, as it instead defines how signal handlers fit into the memory model. This means that (with adjustments for C atomics): int val = 0; std::atomic<bool> flag{false}; void handler(int sig) { if (!set) { val = 1; flag = true; } } int main(void) { signal(SIGINT, handler); while (!flag) { /* Spin waiting for flag */ } return val; } Is valid in C++, but not in C.
- kazinator 3y agostd::anything<whatever> is obviously invalid in C.