How to manage object lifetime with Boost library smart pointers?
There is a scenario I need to solve with shared_ptr and weak_ptr smart pointers.
The two threads, thread 1 and 2, share a common object named A. Each of the threads has a reference to this object. thread 1 decides to delete object A, but at the same time thread 2 can use it. If I used shared_ptr to store references to A's objects in each thread, the object won't get deleted at the right time.
What should I do to be able to delete an object when it is supposed to be and prevent the error in other threads that use that object at the same time?
There are 2 cases:
One thread owns shared data
If thread1 is the "owner" of an object and thread2 should just use it, store weak_process in thread2. Weak pointers do not participate in reference counting; instead, they provide a way to access the shared_ptr to an object if the object still exists. If the object does not 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 helpful.
The data really belongs as
If any of your threads can perform the delete, then you cannot have what I described above. Since both threads need to know the state of the pointer in addition to the underlying object, this might be a case where "pointer to pointer" is useful.
boost::shared_ptr< boost::shared_ptr<T> >
or (via raw ptr)
shared_ptr<T>* sharedObject;
or simply
T** sharedObject;
Why is this useful?
- You only have one referrer for T (actually shared_ptr is rather redundant)
- Both threads can check the state of a single shared pointer (is it NULL? Has it been removed by another thread?)
Pitfalls: - Think what will happen 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 ignore all the concurrency issues with the underlying data, but that's not what you are asking for.
Qt has a QPointer class that does this. Pointers are automatically set to 0 if what they point to is removed.
(Of course, this will only work if you are interested in integrating Qt into your project.)