Boost logo

Boost :

Subject: Re: [boost] storing intrusive_ptr in atomic?!
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2013-10-25 08:50:12


On Friday 25 October 2013 14:35:39 Oliver Kowalke wrote:
> 2013/10/25 Andrey Semashev <andrey.semashev_at_[hidden]>
>
> > That won't work for several reasons. First, as outlined before, you can't
> > store intrusive_ptr in atomic<>. Assuming you store T* instead, then you
> > can't
> > use nullptr as the first argument because CAS accepts it as an lvalue
> > reference. Next, the removal of the pointer is not correct because when
> > CAS
> > fails the pointer is just loaded from the atomic, so you release the
> > pointer
> > and the dangling pointer is left in the array. You have to load e first,
> > then
> > make a loop with CAS and only release if it succeeds and the loaded
> > pointer is
> > not NULL.
>
> array< atomic< T * >, 100 > a{ atomic< T* >( 0) };

That's not correct, it should be:

array< atomic< T * >, 100 > a;
for (auto& p : a)
  p.store(NULL, memory_order_relaxed);

> T * desired = new T();
> T * expected = 0;
> if ( a[index].compare_exchange_strong( expected, desired) ) {
> // desired added
> }
>
> T * expected1 = 0;
> T * expected2 = 0;
> if ( ! a[index].compare_exchange_strong( expected1, expected2) ) {
> // expected1 is not NULL, expected1 removed == a[index] contains NULL
> }

No, that's not right. If compare_exchange_strong returns false, the operation
have failed and a[index] != NULL (at least, that's how compare_exchange_strong
have left it). It should be:

T* expected = a[index].load(memory_order_acquire);
while (!a[index].compare_exchange_weak(expected, NULL, memory_order_release,
memory_order_acquire))
{
}

if (expected)
  // The expected value was removed from the array
else
  // The array element was removed by some other thread


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk