views:

287

answers:

2

Hi,

There is a scenario that i need to solve with shared_ptr and weak_ptr smart pointers.

Two threads, thread 1 & 2, are using a shared object called A. Each of the threads have a reference to that object. thread 1 decides to delete object A but at the same time thread 2 might be using it. If i used shared_ptr to hold object A's references in each thread, the object wont get deleted at the right time.

What should i do to be able to delete the object when its supposed to and prevent an error in other threads that using that object at the same time?

+1  A: 

There's 2 cases:

One thread owns the shared data

If thread1 is the "owner" of the object and thread2 needs to just use it, store a weak_ptr in thread2. Weak pointers do not participate in reference counting, instead they provide a way to access a shared_ptr to the object if the object still exists. If the object doesn't exist, weak_ptr will return an empty/null shared_ptr.

Here's an example:

  class CThread2
  {
  private:
      boost::weak_ptr<T> weakPtr
  public:
   void SetPointer(boost::shared_ptr<T> ptrToAssign)
   {
        weakPtr = ptrToAssign;
   }

   void UsePointer()
   {
        boost::shared_ptr<T> basePtr;
        basePtr = weakPtr.lock()
        if (basePtr)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // thread1 must have deleted the pointer
        }
   }
  };

My answer to this question (link) might also be useful.

The data is truly owned by both

If either of your threads can perform deletion, than you can not have what I describe above. Since both threads need to know the state of the pointer in addition to the underlying object, this may be a case where a "pointer to a pointer" is useful.

 boost::shared_ptr< boost::shared_ptr<T> >

or (via a raw ptr)

shared_ptr<T>* sharedObject;

or just

T** sharedObject;

Why is this useful?

  • You only have one referrer to T (in fact shared_ptr is pretty redundant)
  • Both threads can check the status of the single shared pointer (is it NULL? Was it deleted by the other thread?)

Pitfalls: - Think about what happens when both sides try to delete at the same time, you may need to lock this pointer

Revised Example:

 class CAThread
  {
  private:
      boost::shared_ptr<T>* sharedMemory;
  public:
   void SetPointer(boost::shared_ptr<T>* ptrToAssign)
   {
        assert(sharedMemory != NULL);
        sharedMemory = ptrToAssign;
   }

   void UsePointer()
   {
        // lock as needed
        if (sharedMemory->get() != NULL)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // other thread must have deleted the pointer
        }
   }

   void AssignToPointer()
   {
        // lock as needed
        sharedMemory->reset(new T);
   }

   void DeletePointer()
   {
        // lock as needed
        sharedMemory->reset();
   }
  };

I'm ignoring all the concurrency issues with the underlying data, but that's not really what you're asking about.

Doug T.
What if none of the threads is the owner. They are just worker threads that run a specific unit of work. The threads may access any of the shared objects and may update or delete some of them. I don't have a problem is a shared object gets updated but I don't want any thread to crash if one of the threads deletes one of the objects. It seems to me like i need to reference the object using weak_ptr in both threads, am i right?
O. Askari
If neither of the threads owns the object why are the threads deleting the object?
Bill
A: 

Qt has a QPointer class that does this. The pointers are automatically set to 0 if what they're pointed at is deleted.

(Of course, this would only work if you're interested in integrating Qt into your project.)

Bill
That's what boost::weak_ptr does, as mentioned by the OP.
Alan