There is no ABA issue with this code, but that's really because it doesn't do very much.
The problem is fundamentally that you use compare_and_swap(&p->next, old_next, n)
to make sure that the stack hasn't changed since you last looked at it, but it does not reliably do that.
Between the time you read n->next
and the time you do the compare_and_swap
, other threads could have:
- Popped
n->next
- Pushed a bunch of other stuff
- Re-pushed the old
n->next
Then your compare_and_swap
would succeed even though the stack has changed.
This is not a problem for you, because you never look at any of the fields of n->next
. It doesn't matter that the stack has changed, because all you care about is the n->next
pointer.
If you did have to look inside that object, though, then your code would be broken. For instance, if you added a stack_size
field to atomically keep track of the stack size, then you'd set n->stack_size = old_next->stack_size+1
, and this would be wrong if the stack had changed as above.
So it is not true in general that insert operations are ABA-proof.