fsquirrel
fsquirrel

Reputation: 832

Wait-free queue from Boost.Atomic example crashes

I was looking for C++ implementation of wait-free queue using atomics and found 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_;
};

int main() {
// pop elements
waitfree_queue<int>::node * x = q.pop_all()
while(x) {
  X * tmp = x;
  x = x->next;
  // process tmp->data, probably delete it afterwards
  delete tmp;
}

}

Example at boost official site

I've replaced boost with std and compiled with MSVC 2012. It crashes with next message in console:

Assertion failed: _Order2 != memory_order_release, file c:\program files (x86)\m
icrosoft visual studio 11.0\vc\include\xxatomic, line 742

When I compile original boost it runs w/a crash.

Is it bug in Boost.Atomic or in MSVC implementation of atomic?

Upvotes: 2

Views: 818

Answers (1)

Jesse Good
Jesse Good

Reputation: 52365

It looks like a bug in MSVC implementation. The assertion fails because Order2 is memory_order_release. However, as noted here (which is the same as the C++ standard) (emphasis mine):

The 3-parameter overload is equivalent to the 4-parameter overload with success_order==order, and failure_order==order, except that if order is std::memory_order_acq_rel, then failure_order is std::memory_order_acquire, and if order is std::memory_order_release then failure_order is std::memory_order_relaxed.

In other words, Order2 must be std::memory_order_relaxed for the 4-parameter overload in your case because you passed memory_order_release as order. This is not the case in MSVC's implementation which is a bug. Please report it as a bug if possible.

Upvotes: 1

Related Questions