The Wait-free multi-producer queue in Boost Atomic example:
template<typename T>
class waitfree_queue {
public:
struct node {
T data;
node * next;
};
void push(const T &data)
{
node * n = new node;
n->data = data;
node * stale_head = head_.load(boost::memory_order_relaxed);
do {
n->next = stale_head;
} while (!head_.compare_exchange_weak(stale_head, n, boost::memory_order_release));
}
node * pop_all(void)
{
T * last = pop_all_reverse(), * first = 0;
while(last) {
T * tmp = last;
last = last->next;
tmp->next = first;
first = tmp;
}
return first;
}
waitfree_queue() : head_(0) {}
// alternative interface if ordering is of no importance
node * pop_all_reverse(void)
{
return head_.exchange(0, boost::memory_order_consume);
}
private:
boost::atomic<node *> head_;
};
But I found that the code in push is lock-free rather than wait-free. Suppose multiple producers are calling push, at least one producer can make progress; other producers just run the while loop again until making the progress. There exists a scheduling way that starves a particular thread for an unpredictable time.
The definition of wait-free tells us that any given thread provided with a time-slice will be able to make some progress and eventually complete, while lock-free tells us at least one thread can make progress. So the code above seems to satisfy the definition of lock-free.
Are there mistakes in my understanding?
pop_all_reverse/pop_allare wait-free.