Рассмотрим следующие два потока исполнения:атомное упорядочение памяти и прерывания цикла сообщений
Тема A:
// Initialize stuff...
std::atomic<bool> interrupted = false;
// Launch thread B
// ... Do some useful stuff
// Interrupt B
interrupted = true;
InterruptMessageLoop(B);
Thread B
RunMessageLoop(); // Can exit by itself or due to InterruptMessageLoop
if (interrupted) {
// Do something special
}
вопрос, что у меня есть - может Я уверен, что если нить A действительно вызовет InterruptMessageLoop, поток B увидит атом interrupted
в состоянии true
? (Я имею в виду это «желаемое поведение» ниже)
Проблемы, которую я вижу в том, что, если я правильно понимаю, упорядоченность памяти std::memory_order_seq_cst
, который используется в operator=
вариабельных гарантиях атомных, что не нормально пишет будет переупорядочено после атомной операции и нет нормального читает будет переупорядочено до атомной операции. Но может случиться так, что поток A переупорядочивает InterruptMessageLoop(B)
до атома, тогда поток B прерывает цикл сообщения и считывает неверное значение (относительно логического значения) interrupted
, и только тогда поток A записывает в interrupted
. Это верно? И если да, есть ли способ убедиться, что я получаю поведение, которое я хочу, не прибегая к мьютексу (т. Е. Оберните InterruptMessageLoop и булевскую модификацию в мьютекс и заблокируйте один и тот же мьютекс при чтении)?
Обратите внимание, что я не контролирую реализацию RunMessageLoop
.
Редактировать Обратите внимание, что ситуация, когда я выполняю команду, чтобы прервать цикл и цикл существует нормально (вроде игнорирования моей команды) - это нормально в моем случае, когда поток B считает, что прерывание вызывается цикл обработки сообщений выйти.
Спасибо. Однако, как я сказал в записке, я не контролирую реализацию «RunMessageLoop», поэтому я не могу отличить две ситуации на основе того, что он мне говорит. Тем не менее, ситуация, о которой вы описали, совершенно прекрасна - я беспокоюсь только в том случае, когда я выдаю команду на прерывание цикла, а потом я не могу сказать, что я сделал из потока B. – Rostislav
Я не мог сказать из ваше первоначальное описание, что вы допускаете определенные ошибки, но не некоторые другие ошибки, при принятии решения о том, действительно ли RunMessageLoop прерван потоком A. Но в этом случае взгляните на барьер памяти, например http://stackoverflow.com/questions/8841738/c-memory-barriers-for-atomics. Надеюсь, поможет. –
Да, я понимаю, это было совершенно неясно - спасибо за это! Я посмотрю на барьеры памяти. – Rostislav