58 lines
1.3 KiB
C++
58 lines
1.3 KiB
C++
#include <atomic>
|
|
|
|
template<typename T>
|
|
class lock_free_stack
|
|
{
|
|
private:
|
|
std::atomic<node*> to_be_deleted;
|
|
static void delete_nodes(node* nodes)
|
|
{
|
|
while(nodes)
|
|
{
|
|
node* next=nodes->next;
|
|
delete nodes;
|
|
nodes=next;
|
|
}
|
|
}
|
|
void try_reclaim(node* old_head)
|
|
{
|
|
if(threads_in_pop==1)
|
|
{
|
|
node* nodes_to_delete=to_be_deleted.exchange(nullptr);
|
|
if(!--threads_in_pop)
|
|
{
|
|
delete_nodes(nodes_to_delete);
|
|
}
|
|
else if(nodes_to_delete)
|
|
{
|
|
chain_pending_nodes(nodes_to_delete);
|
|
}
|
|
delete old_head;
|
|
}
|
|
else
|
|
{
|
|
chain_pending_node(old_head);
|
|
--threads_in_pop;
|
|
}
|
|
}
|
|
void chain_pending_nodes(node* nodes)
|
|
{
|
|
node* last=nodes;
|
|
while(node* const next=last->next)
|
|
{
|
|
last=next;
|
|
}
|
|
chain_pending_nodes(nodes,last);
|
|
}
|
|
void chain_pending_nodes(node* first,node* last)
|
|
{
|
|
last->next=to_be_deleted;
|
|
while(!to_be_deleted.compare_exchange_weak(
|
|
last->next,first));
|
|
}
|
|
void chain_pending_node(node* n)
|
|
{
|
|
chain_pending_nodes(n,n);
|
|
}
|
|
};
|