Код: Выделить всё
#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]