In the book C++ Concurrency in Action, the author gave an example of using hazard pointer to implement a lock-free stack data structure. Part of the code is as follows:
std::shared_ptr<T> pop()
{
std::atomic<void*>& hp=get_hazard_pointer_for_current_thread();
node* old_head=head.load();
node* temp;
do
{
temp=old_head;
hp.store(old_head);
old_head=head.load();
} while(old_head!=temp);
// ...
}
The description says that
You have to do this in a
while
loop to ensure that thenode
hasn’t been deleted between the reading of the oldhead
pointer and the setting of the hazard pointer. During this window no other thread knows you’re accessing this particular node. Fortunately, if the oldhead
node is going to be deleted,head
itself must have changed, so you can check this and keep looping until you know that thehead
pointer still has the same value you set your hazard pointer to.
I think the code is flawed because the head
node is subject to the ABA problem. Even if the value of head
remains the same, the node it originally points to may have been deleted. A new head
node is allocated, which happens to have the same address value as the previous one.
head == old_head
implies*head
hasn't changed, which unless I'm mistaken is the problematic assumption which causes ABA problems. – Kokanee