使用引用计数检测正在使用的节点

#include<atomic>
#include <iostream>
#include<thread>
template<typename T>
class lock_free_stack {
private:
	struct node; //前向声明
	struct counted_node_ptr {
		int external_count;
		node* ptr;
	};
	struct node {
		std::shared_ptr<T> data;
		std::atomic<int>internal_count;
		counted_node_ptr next;
		node(T const& data_) : data(std::make_shared<T>(data_)), internal_count(0), next() {}
	};
	std::atomic<counted_node_ptr> head;
	void increase_head_count(counted_node_ptr& old_counter) {
		counted_node_ptr new_counter;
		do {
			new_counter = old_counter;
			++new_counter.external_count;
		} while (!head.compare_exchange_strong(old_counter, new_counter));
		old_counter.external_count = new_counter.external_count;
	}

public:
	~lock_free_stack() {
		while (pop());
	}
	void push(T const& data) {
		counted_node_ptr new_node;
		new_node.ptr = new node(data);
		new_node.external_count = 1;
		new_node.ptr->next = head.load();
		while (!head.compare_exchange_weak(new_node.ptr->next, new_node));
	}
	std::shared_ptr<T>pop() {
		counted_node_ptr old_head = head.load();
		while (1) {
			increase_head_count(old_head);
			node* const ptr = old_head.ptr;
			if (!ptr) return nullptr;
			if (head.compare_exchange_strong(old_head, ptr->next)) {
				std::shared_ptr<T> res;
				res.swap(ptr->data);
				int const count_increase = old_head.external_count - 2;
				if (ptr->internal_count.fetch_add(count_increase) == -count_increase) {
					delete ptr;
				}
				return res;
			}
			else if (ptr->internal_count.fetch_sub(1) == 1) {
				delete ptr;
			}
		}
	}
};
lock_free_stack<int >stk;
std::atomic_int tot = 1;
void push_stack() {
	for (int i = 1; i <= 100; ++i) {
		std::cout << "插入数据:" << i << "\n";
		stk.push(i);
	}
}
void pop_stack() {
	while (tot <= 100) {
		auto x = stk.pop();
		if (x == nullptr) continue;
		std::cout << "第" << tot++ << "次弹出数据:" << *x << "\n";
	}
}
int main() {
	std::thread t1(push_stack);
	std::thread t2(pop_stack);
	std::thread t3(pop_stack);
	
	t1.join(); t2.join(); t3.join();

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值