#include <atomic>
#include <list>
class LockFreeInsertQueue {
public:
void enqueue(int value) {
auto* new_node = new Node{value, nullptr};
while (true) {
auto* tail = tail_.load(std::memory_order_acquire);
auto* next = tail->next.load(std::memory_order_acquire);
if (tail == tail_.load(std::memory_order_acquire)) {
if (next == nullptr) {
// queue is empty, try to insert at the head
if (tail_->next.compare_exchange_weak(next, new_node, std::memory_order_release)) {
tail_ = new_node;
return;
}
} else {
// queue is not empty, try to insert at the tail
if (tail_->compare_exchange_weak(tail, next, std::memory_order_release)) {
next->next.store(new_node, std::memory_order_release);
tail_ = new_node;
return;
}
}
}
}
}
int dequeue() {
while (true) {
auto* head = head_.load(std::memory_order_acquire);
auto* next = head->next;
if (head == tail_.load(std::memory_order_acquire)) {
return -1; // queue is empty
}
if (head_->compare_exchange_weak(head, next, std::memory_order_release)) {
// successfully removed the head
return head->value;
}
}
}
private:
struct Node {
Node* next;
int value;
};
std::atomic<Node*> head_{nullptr};
std::atomic<Node*> tail_{nullptr};
};