views:

2183

answers:

5

I have a question about boost :: shared_ptr.

There are lots of thread.

class CResource
{
xxxxxx
}
class CResourceBase
{
public:
   void SetResource(shared_ptr<CResource> res)
   {
     m_Res = res;
   }

   shared_ptr<CResource> GetResource()
   {
      return m_Res;
   }
private:
   shared_ptr<CResource> m_Res;
}

CResourceBase base;
//----------------------------------------------
Thread A:
    while (true)
    {
       ......
        shared_ptr<CResource> nowResource = base.GetResource();
        nowResource.doSomeThing();
        ...
     }   

Thread B:
    shared_ptr<CResource> nowResource;
    base.SetResource(nowResource);
    ...

//-----------------------------------------------------------

If thread A do not care the nowResource is the newest . Will this part of code have problem? I mean when ThreadB do not SetResource completely, Thread A get a wrong smart point by GetResource?

Another question : what does thread-safe mean? If I do not care about whether the resource is newest, will the shared_ptr nowResource crash the program when the nowResource is released or will the problem destroy the shared_point?

+3  A: 

The answer is pretty simple. No, boost::shared_ptr is not thread-safe

See ZRef: the Thread-Safe Reference Counted Smart Pointer (go down a bit in the provided link)

See Loki's locking pointer as well.

Benoît
The ZRef documentation is referring to a very old version of boost. Boost has had a thread safe reference count since 2002 - http://www.boost.org/users/history/version_1_27_0.
Daniel James
+6  A: 

From the boost documentation:

shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.)

So your usage is not safe, you should use a separate mutex that guards the access to m_res in SetResource/GetResource.

sth
+5  A: 

boost::shared_ptr<> offers a certain level of thread safety. The reference count is manipulated in a thread safe manner (unless you configure boost to disable threading support).

So you can copy a shared_ptr around and the ref_count is maintained correctly. What you cannot do safely in multiple threads is modify the actual shared_ptr object instance itself from multiple threads (such as calling reset() on it from multiple threads). So your usage is not safe - you're modifying the actual shared_ptr instance in multiple threads - you'll need to have your own protection.

In my code, shared_ptr's are generally locals or parameters passed by value, so there's no issue. Getting them from one thread to another I generally use a thread-safe queue.

Of course none of this addresses the thread safety of accessing the object pointed to by the shared_ptr - that's also up to you.

Michael Burr
will this Thread-safe problem cause memory leaking?
A: 

Hi,

I don't understand the answers, in his sample he passes the ptr only by value. Wouldn't such a case retain the correctness of the shared_ptr. It is not the same object. Each copy is its own instance?

Ido

A: 

Add, your class have a Cyclic-references condition; the shared_ptr<CResource> m_Res can't be member of CResourceBase, you can use weak_ptr instead

tntvampire