cppreference.com documents this function as "fence between a thread and a signal handler executed in the same thread". But I found no example on the Internet.
I wonder whether or not the following psuedo-code correctly illustrates the function of std::atomic_signal_fence()
:
int n = 0;
SignalObject s;
void thread_1()
{
s.wait();
std::atomic_signal_fence(std::memory_order_acquire);
assert(1 == n); // never fires ???
}
void thread_2()
{
n = 1;
s.signal();
}
int main()
{
std::thread t1(thread_1);
std::thread t2(thread_2);
t1.join(); t2.join();
}
No, your code does not demonstrate correct usage of atomic_signal_fence
. As you quote cppreference.com, atomic_signal_fence
only perform synchronization between a signal handler and other code running on the same thread. That means that it does not perform synchronization between two different threads. Your example code shows two different threads.
The C++ spec contains the following notes about this function:
Note: compiler optimizations and reorderings of loads and stores are inhibited in the same way as with
atomic_thread_fence
, but the hardware fence instructions that atomic_thread_fence would have inserted are not emitted.Note:
atomic_signal_fence
can be used to specify the order in which actions performed by the thread become visible to the signal handler.
Here's an example of correct, if not motivating, usage:
static_assert(2 == ATOMIC_INT_LOCK_FREE, "this implementation does not guarantee that std::atomic<int> is always lock free.");
std::atomic<int> a = 0;
std::atomic<int> b = 0;
extern "C" void handler(int) {
if (1 == a.load(std::memory_order_relaxed)) {
std::atomic_signal_fence(std::memory_order_acquire);
assert(1 == b.load(std::memory_order_relaxed));
}
std::exit(0);
}
int main() {
std::signal(SIGTERM, &handler);
b.store(1, std::memory_order_relaxed);
std::atomic_signal_fence(std::memory_order_release);
a.store(1, std::memory_order_relaxed);
}
The assertion, if encountered, is guaranteed to hold true.
In your example, you want to use std::atomic_thread_fence
(which generates machine code to perform thread synchronization); not std::atomic_signal_fence
(which only disables compiler memory reordering optimizations on atomic variables).
As was said by others, std::atomic_signal_fence
is only intended for signals on the same thread as the atomic operations (I believe it would also hold true for structured/vectored exception handlers on Windows, but don't quote me on that).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With