Consultant Informatique Réseau et Internet

10 janvier 2011

Are Boost smart pointer thread safe ? (english)

Are Boost smart pointers multi thread safe ? Is there a workaround ?

After a while searching the net to find more information, I had the surprise to find no clear answer to this crucial question. After more research and investigation I finally got my answer and I will share it here.

So, are Boost smart pointers multi thread safe ?

The short answer is: No !

However, in a few specific cases they may be used safely across threads. More information is available here

http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm

in section “Thread safety”. Not that easy to understand ? I agree, a little more details would help.

Why boost smart pointers aren’t theard safe ?

The source of the problem is that a smart pointer manage two informations : the pointer pointing the data and the reference counter. To be thread safe, this two informations must be always worked on using an atomic operation. A quick look to the smart pointers source code shows that this is not the case. Why ? to my opinion, because it would involve locks with an important performance drawback.

Now, is there a workaround ?

Well, since I had to find one for my project I came up with this solution :

- use the intrusive version of boost smart pointers (intrusive_ptr), this way only operations on the pointer pointing the shared object must be managed using atomic operation.

- modify intrusive_ptr source code to make function “swap” thread safe using boost spinlock pool. In source file /boos/smart_ptr/intrusive_ptr.hpp (based on boost version 1.45.0) replace existing “swap” function with this one:

#include <boost/smart_ptr/detail/spinlock_pool.hpp>
#include <boost/memory_order.hpp>

….
void swap(intrusive_ptr & rhs)
{
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this );
sp.lock();
T * tmp = px;
px = rhs.px;
rhs.px = tmp;
sp.unlock();
}
- use atomic functions to manage the reference counter. Below an implementation using a template:
template<class Derived>
class intrusive_ptr_base: public Derived
{
public:
intrusive_ptr_base() : ref_count__(0) { }
friend void intrusive_ptr_add_ref(intrusive_ptr_base* o)
{
//++o->ref_count__;
g_atomic_int_inc(&o->ref_count__);
}
friend void intrusive_ptr_release(intrusive_ptr_base* o)
{
//if (–o->ref_count__ == 0)
if (g_atomic_int_exchange_and_add(&o->ref_count__,-1)==1)
{
delete static_cast<Derived*>(o);
}
}
volatile int ref_count__;
};

To declare an intrusive thread safe smart pointer, do as below:

boost::intrusive_ptr< intrusive_ptr_base< MyObject > > smart_MyObject;

Pas de commentaire

Pas encore de commentaire.

Flux RSS des commentaires de cet article.

Désolé, les commentaires sont fermés pour le moment.

Propulsé par WordPress