In C++11, you can use a shared_ptr<>
to establish an ownership relation with an object or variable and weak_ptr<>
to safely reference t
While you can't get a "weak" pointer to a uniquely owned object for free, the concept is useful and is used in a couple systems. See Chromium's WeakPtr and QT's QPointer for implementations.
Chromium's WeakPtr is implemented intrusively by storing a shared_ptr inside the weak-referenceable object and marking it invalid when the object is destroyed. WeakPtrs then reference that ControlBlock and check whether it's valid before handing out their raw pointer. I assume QT's QPointer is implemented similarly. Because ownership isn't shared, the original object is destroyed deterministically.
However, this means that dereferencing the WeakUniquePtr
isn't thread-safe:
Thread 1:
unique_ptr obj(new MyObject);
thread2.send(obj->AsWeakPtr());
...
obj.reset(); // A
Thread2:
void receive(WeakUniquePtr weak_obj) {
if (MyObject* obj = weak_obj.get()) {
// B
obj->use();
}
}
If line A
happens to run concurrently with line B
, thread 2 will wind up using a dangling pointer. std::weak_ptr
would prevent this problem by atomically taking a shared owning reference to the object before letting thread 2 use it, but that violates the assumption above that the object is owned uniquely. That means that any use of a WeakUniquePtr
needs to be synchronized with the destruction of the real object, and the simplest way to do that is to require that they're done in a message loop on the same thread. (Note that it's still completely safe to copy the WeakUniquePtr
back and forth across threads before using it.)
One could imagine using a custom deleter in std::unique_ptr
to implement this using standard library types, but that's left as an exercise for the reader.