std::experimental::atomic_shared_ptr<T> provides atomic operations on shared-pointer ownership. It supports load, store, exchange, and compare-exchange, and requires the <experimental/atomic> header. The type may or may not be lock-free on a given implementation; check with is_lock_free(). section 5.2.7 section 7.2.4
Use the dedicated type to:
- Make shared-pointer accesses atomic through the type’s member operations, rather than relying on consistently using atomic free functions with a plain std::shared_ptr. section 5.2.7 section 7.2.4
- Manage reference counting correctly while using atomic operations; if the implementation is not lock-free, this type does not itself provide lock-free operation. section 7.2.4
Listing 7.10. Stack implementation using std::experimental::atomic_shared_ptr<>
template<typename T>
class lock_free_stack
{
private:
struct node
{
std::shared_ptr<T> data;
std::experimental::atomic_shared_ptr<node> next;
node(T const& data_):
data(std::make_shared<T>(data_))
{}
};
std::experimental::atomic_shared_ptr<node> head;
public:
void push(T const& data)
{
std::shared_ptr<node> const new_node=std::make_shared<node>(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
std::shared_ptr<T> pop()
{
std::shared_ptr<node> old_head=head.load();
while(old_head && !head.compare_exchange_weak(
old_head,old_head->next.load()));
if(old_head) {
old_head->next=std::shared_ptr<node>();
return old_head->data;
}
return std::shared_ptr<T>();
}
~lock_free_stack(){
while(pop());
}
};
The stack stores its head and each node’s next pointer as atomic_shared_ptr values, using member loads and compare-exchange operations to update them. section 7.2.4
