Неправильное поведение кольцевого буфера с использованием std::atomicC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Неправильное поведение кольцевого буфера с использованием std::atomic

Сообщение Anonymous »

Приведенный ниже сценарий представляет собой полностью автономное воспроизведение. Он содержит класс Racer, который моделирует кольцевой буфер. Один поток пытается несколько раз продвинуть головку, а другой поток несколько раз пытается продвинуть хвост. Когда head == Tail, Racer считается пустым. Когда хвост+1 == голова, Гонщик считается заполненным.
Перемещение хвоста, когда Гонщик заполнен, ничего не дает. Продвижение головы, когда Гонщик набрал полный блок, пока хвост также не будет выдвинут вперед.
Или, по крайней мере, это цель. На самом деле программа обнаруживает нарушение инварианта вскоре после запуска. В частности, когда голова блокируется, а затем разблокируется при движении хвоста, Гонщик каким-то образом не видит изменений ни в положении головы, ни в положении хвоста.

Код: Выделить всё

#include 
#include 
#include 
#include 

template 
struct Racer {
std::atomic head{0};
std::atomic tail{0};
std::atomic update_counter{0};

bool try_advance_tail() {
int h = head; // seq_cst load
int t = tail; // seq_cst load

int next = (t + 1) % Size;
if (next == h) return false;  // full

tail = next;  // seq_cst store

// Publish change and notify.
update_counter.fetch_add(1, std::memory_order_release);
update_counter.notify_one();
return true;
}

void try_advance_head() {
unsigned long long old_ctr = update_counter; // seq_cst load
int orig_h = head;
int orig_t = tail;
bool orig_empty = (orig_h == orig_t);

if (orig_empty) {
// Wait until counter changes, acquire on read.
update_counter.wait(old_ctr, std::memory_order_acquire);
}

unsigned long long new_ctr = update_counter; // seq_cst load
int new_h = head; // seq_cst
int new_t = tail; // seq_cst
bool new_empty = (new_h == new_t);

if (orig_empty && new_ctr != old_ctr && new_empty) {
std::cerr 

Подробнее здесь: [url]https://stackoverflow.com/questions/79838618/misbehaving-circular-ring-buffer-using-stdatomic[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»