在Williams的 C ++并发行动中第二版。在第213页上,实现了无锁堆栈(如下所示)。它泄漏节点,因此是不完整的,但这与我的问题无关。我的问题是他没有显式初始化std::atomic<node*> head
指针,然后在pop()
函数中取消引用该指针-这不是未定义的行为吗?
默认初始化的
std::atomic<T>
不包含T对象,其唯一有效的用途是std::atomic_init
的销毁和初始化
所有指针类型的部分专业化
std::atomic<U*>
。这些专业具有标准布局,琐碎的默认构造函数和琐碎的析构函数。
我想我看不到任何东西,因为(甚至不完整) 在cppreference上实现无锁堆栈也不在乎 初始化原子头指针。有人可以向我解释为什么这种用法合法吗?
这是威廉姆斯的密码
template<typename T>
class lock_free_stack
{
private:
struct node
{
std::shared_ptr<T> data;
node* next;
node(T const& data_):
data(std::make_shared<T>(data_))
{}
};
std::atomic<node*> head; // <-- Default constructor
public:
void push(T const& data)
{
node* const new_node=new node(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
std::shared_ptr<T> pop()
{
node* old_head=head.load();
while(old_head &&
!head.compare_exchange_weak(old_head,
old_head->next));// uninitialized ptr?
return old_head ? old_head->data : std::shared_ptr<T>();
}
};