Код: Выделить всё
struct TwoInts {
int a;
int b;
};
static thread_local std::atomic t_two_ints;
void Foo() {
// Publish a TwoInts struct for use by HandleSignal while we run. Use a
// release fence before publishing to prevent the compiler from reordering
// the initialization code to after the pointer is published.
std::optional s = TwoInts{17, 19};
std::atomic_signal_fence(std::memory_order_release);
t_two_ints.store(&*s, std::memory_order_relaxed);
// Do some other work…
// Unpublish the struct before we destroy it. For exposition's sake we
// destroy it explicitly by resetting the optional.
t_two_ints.store(nullptr, std::memory_order_relaxed);
s.reset();
}
void HandleSignal() {
// Load the pointer, using an acquire load to pair with the release fence
// in Foo, so that we see the side effects of initializing the struct.
const TwoInts* const s = t_two_ints.load(std::memory_order_acquire);
if (s != nullptr && s->b != s->a + 2) {
std::quick_exit();
}
}
Код: Выделить всё
FooА как насчет другого конца? Нужно ли нам что-то сделать, чтобы предотвратить переупорядочение вызова ~MyStruct перед нулевым хранилищем в Foo? Кажется, что здесь должна возникнуть обратная задача, но не совсем ясно, как использовать ограничения для ее решения, прибегая к чему-то вроде забора получения и операции сравнения и замены. Есть ли какая-то другая причина, по которой мы можем быть уверены, что вызов деструктора не будет поднят над записью?
В идеале я ищу ответ юриста по языку с цитатами из стандарта. C++20 и C++23 подходят.
Подробнее здесь: https://stackoverflow.com/questions/798 ... omic-write
Мобильная версия