Это невозможно, так как это не имеет никакого смысла.
Ваш код получит действительные значения для сравнения, но дает очень мало гарантий, когда эти значения будут получены. Поэтому, если проверка завершается успешно, все, что вы будете знать, это то, что readIdx
был в некоторый момент времени равным значению, которое writeIdx + 1
дало в определенный момент времени. Эти два момента времени в основном не связаны. В частности, допускается, чтобы ни в один момент времени значение readIdx
не было равно значению writeIdx + 1
, но все же проверка прошла успешно.
Вот почему это на самом деле не проблема: вы не сможете установить, что понятие атомистики равно равным в то же время без введения дополнительной блокировки. Проблема в том, что любой код, зависящий от этого условия, должен быть частью того же атомного блока выполнения, который выполняет проверку. Если это не так, условие может измениться, прежде чем код завершит выполнение.
С другой стороны, если какая-либо часть кода не зависит от состояния, нет смысла вводить его в качестве концепции в первую очередь.
Итак, вот как это сделать. Вернитесь назад и пересмотрите, действительно ли у вас код, который зависит от того, что обе переменные должны иметь ожидаемые значения в момент выполнения кода. Если это так, вам нужно защитить этот код с помощью блокировки. Если нет, вполне вероятно, что вам вообще не нужно проверять состояние, так как гарантии, предоставленные вашим текущим кодом, вероятно, слишком слабы, чтобы быть реальным использованием.
Что вы подразумеваете под «атомным» здесь? Какая последовательность оценок, которые этот код может заметить, что вы хотите предотвратить? Условие эквивалентно 'writeIdx.load() + 1 == readIdx.load()'. Разумеется, два вызова 'load()' являются атомарными; остальное действует на простые 'uint32_t'. –
@IgorTandetnik: Если в системе есть еще один поток, он может изменить 'writeIdX' после того, как поток OP прочитает его, и прежде чем он прочитает' readIdx'. В этом случае OP, по-видимому, хочет, чтобы два 'load()' вызова выполнялись атомарно * как группа *, а не для каждой отдельной 'load()' для атома (что они, по-видимому, есть). –
@NathanFellman: Как это будет отличаться наблюдаемым поведением от ситуации, когда 'writeIdx' изменяется сразу после загрузки обеих атомов? Конечный результат точно такой же, поэтому почему нужно предотвратить один случай, а не другой? –