One of the key things to keep in mind when designing a stack is to ensure that a pushed value is safe to return from another thread. Also important is ensuring that only one thread returns a value.
In the previous sections, we implemented a lock-based stack that wrapped std::stack. We know that a stack is not a real data structure but an adapter. Usually, when implementing a stack, we choose either a vector or a linked list as its underlying data structure. Let's look at an example of a lock-free stack based on a linked list. Pushing a new element into the stack involves creating a new list node, setting its next pointer to the current head node, and then setting the head node to point to the newly inserted node. ...