Boost logo

Boost :

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


On Friday 25 October 2013 13:43:38 Oliver Kowalke wrote:
> 2013/10/25 Giovanni Piero Deretta <gpderetta_at_[hidden]>
>
> > that's the tricky part. To adjust the reference count, you must load and
> > dereference the pointer itself, but between those two operations another
> > thread might come in, replace the pointer, adjust the original pointer
> > count down and free the pointed object, together with the counter. You
> > need
> > some way to defer destruction till a safe point (RCU, hazard pointers,
> > etc).
>
> what about this
>
> // use-counter in T is an atomic too
> array< atomic< intrusive_ptr< T > >, 100 > a;
>
> intrusive_ptr< T > p(...);
> intrusive_ptr_add_ref( p.get() );
> // add an intrusive_ptr to the array
> if ( a[index].compare_exchange_strong(null_ptr,p) ) {
> // successful added
> }
>
> // remove an interusive_ptr from array
> intrusive_ptr< T > e; // points to nothing
> if ( ! a[index].compare_exchange_strong(e, null_ptr) ) {
> // successfull removed
> intrusive_ptr_release( e.get() );
> }

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.


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