4

I'm thinking of using boost::weak_ptr to implement a pool of objects such that they will get reaped when nobody is using one of the objects. My concern, though, is that it's a multi-threaded environment, and it seems there's a race condition between the last shared_ptr to an object going out of scope and a new shared_ptr being constructed from the weak_ptr. Normally, you'd protect such operations with lock or something; however, the whole point here is that you don't know when the shared_ptr might be going out of scope.

Am I misunderstanding something about boost::shared_ptr and boost::weak_ptr? If not, does anybody have any good suggestions on what to do?

Thanks.

Andrew

3 Answers3

11

To use a weak_ptr, you normally have to grab a strong reference by constructing a shared_ptr with it. This last step is atomic: you either get a strong reference back, or you get a bad_weak_ptr exception thrown. (Alternatively, call lock() on the weak_ptr, and either get a strong reference or null.)

Example (with lock(); easy enough to adapt to the other style):

void do_something(weak_ptr<foo> weak) {
    // Grab strong reference
    shared_ptr<foo> strong(weak.lock());
    if (strong) {
        // We now have a strong reference to use
    } else {
        // No strong references left; object already freed
    }
}
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • 3
    I believe there's no need to test whether your shared_ptr is valid or not, because the constructor will throw bad_weak_ptr exceptions if your week_ptr points to the deleted object. Or you should use weak_ptr::lock() which doesn't throw but can return a shared_ptr which points to NULL. – Serge Jan 29 '10 at 07:41
  • 1
    So it's atomic? The Thread Safety section in the man page leaves some doubt in my mind. – Andrew Certain Jan 29 '10 at 08:01
  • @Serge: Thank you! I'm going to fix my post. – C. K. Young Jan 29 '10 at 14:51
  • @ChrisJester-Young, would mind having a look at my post: http://stackoverflow.com/questions/9948113/boostweak-ptrt-lock-crashes-with-a-sigsegv-segmentation-fault ? My `weak_ptr.lock()` method itself crashed. – Peter Lee Mar 30 '12 at 18:21
3

Both boost::weak_ptr and boost::shared_ptr are similar if it comes to thread safety: they are not thread safe if there is a risk that object is going to be destroyed somewhere. If your object referenced in boost::shared_ptr or weak_ptr is being referenced permanently somewhere, then use can use shared/weak ptrs without any risk.

But if some operation is going to dereference the last living instance of object, then at that time you cannot do some operations on weak_ptr: in particular: you cannot assign weak_ptr to another weak_ptr because it uses shared_ptr internally. Also, you cannot use lock because the result is undefined. Also, expired() method is useless to: it may return true, but then next line of your code, your object might be already expired.

Pigueiras
  • 18,778
  • 10
  • 64
  • 87
0

Yes, ish. In terms of accessing the pointers, Boost should have made everything safe; that's part of their point.

However, if you're expecting to have a delay between when the last shared_ptr goes out, and when you want to make the next one, you'll get a null pointer. (If you're checking appropriately, you should then have an appropro fail case).

But you can't end up with an invalid shared_ptr

Narfanator
  • 5,595
  • 3
  • 39
  • 71