Correct CAS Still Crashes

Node* pop() {
    Node* old = head.load(std::memory_order_acquire);
    while (old && !head.compare_exchange_weak(old, old->next,
                      std::memory_order_acquire,
                      std::memory_order_relaxed)) {
        // retry
    }
    if (old) delete old;              // caller already copied the value out
    return old;
}

Assume ABA has been eliminated: head now packs a modification counter next to the address, with the tag arithmetic elided from the snippet, and ThreadSanitizer reports no data race on head. At 16 threads the program still faults intermittently while evaluating the old->next argument. What is missing?

A

A wider tag field, since 16 threads can wrap the counter inside a single CAS window.

B

A safe memory reclamation scheme. The read of old->next can run after another thread has popped and deleted that same node, so delete has to be deferred until no thread still holds a reference, via hazard pointers or an RCU-style grace period.

C

A std::atomic_thread_fence(std::memory_order_release) before the delete, so the node's memory is published before it is reclaimed.

D

compare_exchange_strong instead of the weak form, since a spurious failure leaves the loop dereferencing a pointer it has already discarded.