结合外部计数及内部计数,代码目前只能在VS平台跑,clion和vc报编译器错误,
#include<bits/stdc++.h>
#include<thread>
#include<mutex>
#include<atomic>
using namespace std;
template<typename T>
class lock_free_queue {
public:
atomic<int> size_;
private:
struct node;
struct counted_node_ptr {//next结点
int external_count = 0;
node* ptr = nullptr;
};
atomic<counted_node_ptr> head;
atomic<counted_node_ptr> tail;
struct node_counter {//结点计数器信息
int internal_count; // 内部引用计数器值
int external_counters;
};
struct node {
public:
atomic<T*> data;
atomic<node_counter> count;//结点计数器的信息
atomic<counted_node_ptr> next;
node() {
//node_counter new_count {0, 2}; //被tail指针和上一个结点的next指针指涉 引用计数为2 每次的新节点都是尾部
node_counter new_count;
new_count.internal_count = 0;
new_count.external_counters = 2;
count.store(new_count);
next = { 0 };
}
void release_ref() {
node_counter old_counter = count.load(memory_order_relaxed);
node_counter new_counter;
do {
new_counter = old_counter;
--new_counter.internal_count;//internal自减
} while (!count.compare_exchange_strong(old_counter, new_counter, memory_order_acquire, memory_order_relaxed));
if (!new_counter.internal_count && !new_counter.external_counters)
delete this;
}
};
static void increase_external_count(atomic<counted_node_ptr>& counter,
counted_node_ptr& old_counter) {
counted_node_ptr new_counter;
do {
new_counter = old_counter;
++new_counter.external_count;
} while (!counter.compare_exchange_strong(old_counter, new_counter, memory_order_acquire, memory_order_relaxed));
old_counter.external_count = new_counter.external_count;
}
static void free_external_counter(counted_node_ptr& old_node_ptr) {
node* const ptr = old_node_ptr.ptr;
int const count_increase = old_node_ptr.external_count - 2;
node_counter old_counter = ptr->count.load(memory_order_relaxed);
node_counter new_counter;
do {
new_counter = old_counter;
--new_counter.external_counters;
new_counter.internal_count += count_increase;
} while (!ptr->count.compare_exchange_strong(old_counter, new_counter, memory_order_acquire, memory_order_relaxed));
if (!new_counter.external_counters && !new_counter.internal_count)
delete ptr;
}
void set_new_tail(counted_node_ptr& old_tail,
counted_node_ptr const& new_tail) {
node* const current_tail_ptr = old_tail.ptr;
while (!tail.compare_exchange_weak(old_tail, new_tail) && old_tail.ptr == current_tail_ptr)
;
if (old_tail.ptr == current_tail_ptr)
free_external_counter(old_tail);
else
current_tail_ptr->release_ref();
}
public:
lock_free_queue() {
counted_node_ptr headl;
headl.ptr = new node();
headl.external_count = 1;
head.store(headl);
tail.store(headl);
this->size_ = 0;
}
void push(T new_value) {
unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr = new node;
new_next.external_count = 1;//自身为tail 被tail指针指涉
counted_node_ptr old_tail = tail.load();
while (true) {
increase_external_count(tail, old_tail);//当前节点外部引用计数增加
/*若有其他线程同时压入数据,就会始终看不到nullptr,只会看到传入的新值,导致重新循环(忙等--实质的锁),被阻塞的
线程一直消耗CPU周期,等到最初调用push的线程执行完毕才停止*/
T* old_data = nullptr;
/*上述问题推导出 让等待的线程协助正在push的线程,以实现无锁队列*/
if (old_tail.ptr->data.compare_exchange_strong(old_data, new_data.get()))
{
counted_node_ptr old_next = { 0 };
if (!old_tail.ptr->next.compare_exchange_strong(old_next, new_next)) {
delete new_next.ptr;
new_next = old_next;
}
set_new_tail(old_tail, new_next);
new_data.release();
break;
}
else {
counted_node_ptr old_next = { 0 };
if (old_tail.ptr->next.compare_exchange_strong(old_next, new_next)) {
old_next = new_next;
new_next.ptr = new node;
}
set_new_tail(old_tail, old_next);
}
} size_++;
}
unique_ptr<T> pop() {
counted_node_ptr old_head = head.load(memory_order_relaxed);
for (;;) {
increase_external_count(head, old_head);
node* const ptr = old_head.ptr;
if (ptr == tail.load().ptr) {
return unique_ptr<T>();
}
counted_node_ptr next = ptr->next.load();
//线程将数据收为己有
if (head.compare_exchange_strong(old_head, next)) {
T* const res = ptr->data.exchange(nullptr);
free_external_counter(old_head);
return unique_ptr<T>(res);
}
ptr->release_ref();
}
}
~lock_free_queue() {
}
};
template<typename T>
void init(lock_free_queue<T>& q) {
for (int i = 0; i < 1000; i++)
q.push(i);
}
template<typename T>
void put(lock_free_queue<T>& q) {
int h = 1000; unique_ptr<int> v;
while (true) {
v = q.pop();
if (v)
cout << "数值:" << *v << " " << endl;
else
return;
}
}
int main() {
cout << "程开始" << endl;
lock_free_queue<int> q;
cout << " size:" << q.size_ << endl;
this_thread::sleep_for(chrono::seconds(2));
vector<thread> ts;
for (int i = 0; i < 50; i++) {
ts.push_back(thread(&init<int>, ref(q)));
}
for (auto& x : ts)
x.join();
vector<thread> ts2;
for (int i = 0; i < 5; i++) {
ts2.push_back(thread(&put<int>, ref(q)));
}
for (auto& x : ts2)
x.join();
cout << "程序结束" << endl;
return 0;
}