Почему моя реализация стека без блокировки не работает в Windows и более старых системах Linux?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Почему моя реализация стека без блокировки не работает в Windows и более старых системах Linux?

Сообщение Anonymous »

Я работаю над реализацией стека без блокировок с использованием C++ и CAS (compare_exchange_strong/compare_exchange_weak). Кажется, что реализация работает нормально в современных системах Linux, но не работает в Windows и некоторых старых версиях Linux. Ниже приведен полный код для тестирования безопасности потоков с участием нескольких производителей и потребителей:

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
using namespace std;

template 
class LockFreeStack {
public:
struct Node {
T data;
Node* next;
Node(const T& value) : data(value), next(nullptr) {}
};

LockFreeStack() : head(nullptr) {}
~LockFreeStack() {
while (pop());
}

bool empty() {
return head == nullptr;
}

void push(const T& value) {
Node* new_node = new Node(value);
auto q = head.load(memory_order_relaxed);

do {
new_node->next = q;
} while (!head.compare_exchange_strong(q, new_node)); // Neither compare_exchange_strong nor compare_exchange_weak can guarantee thread safety.
}

Node* pop() {
auto q = head.load(memory_order_acquire);
while (q && !head.compare_exchange_strong(q, q->next)) {}
return q;
}

private:
atomic head;
};

int RollDice() {
return rand() % 500 + 1;
}

void test_lock_free_stack() {
LockFreeStack stack;

const int num_producers = 15;
const int num_consumers = 15;
const int num_elements_per_producer = 100000;

vector producers;
vector consumers;

vector producer_counts(num_producers, 0);
vector consumer_counts(num_consumers, 0);

unordered_set consumed_set[num_consumers];
mutex consumed_set_mutex;

atomic producers_done(0);

// Producer threads
for (int i = 0; i < num_producers; ++i) {
producers.emplace_back([&stack, &producer_counts, i, num_elements_per_producer, &producers_done]() {
srand(time(NULL));
this_thread::sleep_for(chrono::milliseconds(RollDice()));
for (int j = 0; j < num_elements_per_producer; ++j) {
int value = i * num_elements_per_producer + j;
stack.push(value);
producer_counts[i]++;
}
producers_done++;
});
}

// Consumer threads
for (int i = 0; i < num_consumers; ++i) {
consumers.emplace_back([&stack, &consumer_counts, i, &consumed_set, &consumed_set_mutex, &producers_done, num_producers]() {
LockFreeStack::Node* value;
while (producers_done != num_producers || !stack.empty()) {
value = stack.pop();
if (value) {
{
consumed_set[i].insert(value->data);
}
delete value;
consumer_counts[i]++;
}
}
});
}

for (auto& producer : producers) {
producer.join();
}
for (auto& consumer : consumers) {
consumer.join();
}

int total_produced = 0;
for (int count : producer_counts) {
total_produced += count;
}

int total_consumed = 0;
for (int count : consumer_counts) {
total_consumed += count;
}

if (total_produced != total_consumed) {
cout 

Подробнее здесь: [url]https://stackoverflow.com/questions/79319131/why-does-my-lock-free-stack-implementation-fail-on-windows-and-older-linux-syste[/url]
Ответить

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

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

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

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

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