Предполагая, что выровненные указательные нагрузки и хранилища естественно атомарны на целевой платформе, в чем разница между ними:
// Case 1: Dumb pointer, manual fence
int* ptr;
// ...
std::atomic_thread_fence(std::memory_order_release);
ptr = new int(-4);
// Case 2: atomic var, automatic fence
std::atomic<int*> ptr;
// ...
ptr.store(new int(-4), std::memory_order_release);
и это:
// Case 3: atomic var, manual fence
std::atomic<int*> ptr;
// ...
std::atomic_thread_fence(std::memory_order_release);
ptr.store(new int(-4), std::memory_order_relaxed);
У меня создалось впечатление, что все они эквивалентны, однако Relacy обнаруживает гонку данных в первый случай (только):
struct test_relacy_behaviour : public rl::test_suite<test_relacy_behaviour, 2>
{
rl::var<std::string*> ptr;
rl::var<int> data;
void before()
{
ptr($) = nullptr;
rl::atomic_thread_fence(rl::memory_order_seq_cst);
}
void thread(unsigned int id)
{
if (id == 0) {
std::string* p = new std::string("Hello");
data($) = 42;
rl::atomic_thread_fence(rl::memory_order_release);
ptr($) = p;
}
else {
std::string* p2 = ptr($); // <-- Test fails here after the first thread completely finishes executing (no contention)
rl::atomic_thread_fence(rl::memory_order_acquire);
RL_ASSERT(!p2 || *p2 == "Hello" && data($) == 42);
}
}
void after()
{
delete ptr($);
}
};
Я связался с автором Relacy, чтобы узнать, было ли это ожидаемое поведение; он говорит, что в моей тестовой ситуации действительно есть гонка данных. Однако у меня проблемы с этим; может кто-нибудь указать мне, что такое гонка? Самое главное, каковы различия между этими тремя случаями?
Обновление. Мне пришло в голову, что Relacy может просто жаловаться на атомарность (или ее отсутствие), а не на переменную, доступную через потоки... в конце концов, она не знает что я намерен использовать этот код только на платформах, где выровненный целочисленный/указательный доступ естественно атомный.
Другое обновление. Джефф Прешинг написал отличное сообщение в блоге объясняя разницу между явными заборами и встроенными ( "ограждения" против "операций" ). Случаи 2 и 3, по-видимому, не эквивалентны! (В некоторых тонких обстоятельствах, во всяком случае.)