在学习C++多并发的时候模拟写栈时,当使用下面的pop函数时,偶发性导致coredump,但是我理解中的compare_exchange_weak将设定值给当前值时只在当前值与期望值相同的情况下,请问这个coredump触发因是因为哪里导致的哈
template<typename T>
class mystack
{
struct node
{
std::shared_ptr<T> data; // 1 指针获取数据
node* next = nullptr;
node(T const& data_):
data(std::make_shared<T>(data_)) // 2 让std::shared_ptr指向新分配出来的T
{
next = nullptr;
}
};
std::atomic<int> threads_in_pop;
std::atomic<node*> head;
std::atomic<node*> need_clear_list;
void clear_all_need_list(node *clear_node)
{
while(clear_node)
{
node *temp_node = clear_node ->next;
delete clear_node;
clear_node = temp_node;
}
}
void chain_pending_nodes(node *nodes)
{
if(!nodes)
{
return;
}
node *last = nodes;
while(node *next = last->next)
{
std::cout<<"find next"<<std::endl;
last = next;
}
chain_pending_nodes(nodes,last);
}
void chain_pending_nodes(node *first,node *last)
{
last->next = need_clear_list.load();
while(!need_clear_list.compare_exchange_weak(last->next,first));
}
void chain_pending_node(node *nodes)
{
chain_pending_nodes(nodes,nodes);
}
void clear_pop_threads(node *clear_data)
{
if(threads_in_pop == 1)
{
node *old_head = need_clear_list.exchange(nullptr);
if(threads_in_pop.fetch_sub(1) == 1)
{
clear_all_need_list(old_head);
}
else
{
chain_pending_nodes(old_head);
}
delete clear_data;
}
else
{
// clear_data ->next = nullptr;
// chain_pending_nodes(clear_data); //理论上与上方的一致
chain_pending_node(clear_data);
threads_in_pop.fetch_sub(1);
std::cout<<"threads_in_pop != 1"<<std::endl;
}
}
public:
mystack()
{
threads_in_pop = 0;
need_clear_list.store(nullptr);
std::cout<<"create id:"<<std::this_thread::get_id()<<std::endl;
head.store(nullptr); //如果不设置初值,head将不一定为nullptr
}
~mystack()
{
std::cout<<"~id:"<<std::this_thread::get_id()<<std::endl;
}
void push(T const new_data)
{
node *newnode = new node(new_data);
newnode->next = head.load();
while(!head.compare_exchange_weak(newnode->next,newnode));
}
std::shared_ptr<T> pop()
{
threads_in_pop.fetch_add(1);
node *oldnode = head.load();
while( oldnode && !head.compare_exchange_weak(oldnode,oldnode->next,std::memory_order_release,std::memory_order_relaxed));
std::shared_ptr<T> res;
if(oldnode)
{
res.swap(oldnode->data);
delete oldnode; //将会导致coredump
}
// clear_pop_threads(oldnode);
return res;
}
};