boost::weak_ptr usage in multithreaded environments

Hello all, [long story short: I'd like to know whether a weak_ptr.lock() counts as a "shared pointer read" or as a "shared pointer write" ] I'm using boost shared pointers in an multi-threaded app. Basically, my app maintains a "forest" of "context trees" - i.e. I have a map from a "file name" to a "global context" that organizes the information for that file. The "global context" in the map is basically the root node of a tree of "local contexts" in that file. The tree is kept with boost:shared_ptr<> on the way down (father-son relations) and boost::weak_ptr<> on the way up (son->father pointers). I have added proper synchronization to the data structure... I think. I use reader/writer locks (only one writer allowed, but arbitrary number of readers) and I'm still getting sporadic crashes, especially when constructing a "global context" (root node) shared_ptr<> from a weak_ptr<> - using lock(). I am assuming in my app. that weak_ptr<>.lock() only requires a "read lock", not a "write lock".. is this true? I've checked out the page at http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/shared_ptr.htm#ThreadSaf..., but there's nothing about weak_ptr there... Thanks, Virgil.

Virgil Palanciuc wrote:
Hello all,
[long story short: I'd like to know whether a weak_ptr.lock() counts as a "shared pointer read" or as a "shared pointer write" ]
It is a "const" member function and counts as a read.
I'm using boost shared pointers in an multi-threaded app. Basically, my app maintains a "forest" of "context trees" - i.e. I have a map from a "file name" to a "global context" that organizes the information for that file. The "global context" in the map is basically the root node of a tree of "local contexts" in that file. The tree is kept with boost:shared_ptr<> on the way down (father-son relations) and boost::weak_ptr<> on the way up (son->father pointers).
I have added proper synchronization to the data structure... I think. I use reader/writer locks (only one writer allowed, but arbitrary number of readers) and I'm still getting sporadic crashes, especially when constructing a "global context" (root node) shared_ptr<> from a weak_ptr<> - using lock().
Would it be possible to extract a simplified example in which the crashes still occur?

[long story short: I'd like to know whether a weak_ptr.lock() counts as a "shared pointer read" or as a "shared pointer write" ]
It is a "const" member function and counts as a read. Yeah, it's const allright... which means it doesn't modify the underlying weak_ptr<> object, not that it doesn't modify the shared "shared_ptr" counter. To me, it feels that it should count as a "read" (since it's allowed to "copy" the same shared_ptr from two threads simultaneously, it *should* be allowed to create copies from weak_ptrs, too - but I thought I should double-check).
Would it be possible to extract a simplified example in which the crashes still occur? Don't think so :(, it's extremely hard to reproduce, currently it only (sort of) reproduces in Snow Leopard.. and probably would no longer reproduce if I'd trim the "application" from around it (assuming that it would be feasible, at all, to trim the rest of the app)
Creating and destroying shared_ptr (including those created through weak_ptr::lock) doesn't require any locking at all, as far as the reference counting goes. Unless you are trying to simultaneously access the same weak_ptr/shared_ptr object (rather than copies pointing at the same thing) from different threads? What if I were accessing the very same shared_ptr/weak_ptr object from different threads? Is this problematic (i.e. "read access", not "read/write")? As I said, I have a global map that keeps the "tree roots"(as shared_ptr), and potentially many "walkers" that walk the tree. If two
On Mon, Feb 1, 2010 at 5:23 PM, Frank Mori Hess

Virgil Palanciuc wrote:
As I said, I have a global map that keeps the "tree roots"(as shared_ptr), and potentially many "walkers" that walk the tree. If two threads get the root from the global map - they'd get to read the very same shared_ptr variable; If two threads happen to walk the same node and try to get the "father" - they'd get to "lock" on the same weak_ptr variable simultaneously. Is that a problem?
No, it should work.
(assuming that I have "read locks" in place - i.e. there is currently no "writer" thread that is trying to completely remove a tree from the global map) [BTW - that's the only way that "writing" ever occurs: a "writer thread" builds an alternate version of a tree, and then acquires a write lock and replaces the old tree in the global map; there may be still walker threads that walk the "old tree" - but that should be ok since they keep a copy of the shared_ptr, basically guaranteeing that the old tree itself is not destroyed as long as there is a walker on it ]
Everything you describe sounds fine, at least in principle. There could be a bug in weak_ptr, a bug in your logic somewhere, or a bug in Snow Leopard's gcc (such things have happened in the past). If you suspect weak_ptr you could try to write a simple test that repeatedly locks the same instance from several threads and see if it cracks under the pressure.

Zitat von Peter Dimov
Everything you describe sounds fine, at least in principle. There could be a bug in weak_ptr, a bug in your logic somewhere, or a bug in Snow Leopard's gcc (such things have happened in the past). If you
I doubt it is a bug in weak_ptr, weak_ptr::lock() is pretty much the same code as copying a shared_ptr. (see constructors of shared_count). have you tried valgrind? afaik there is an experimental port for mac os. if shared_ptr/weak_ptr delete an object that is still in use valgrind should catch that.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Monday 01 February 2010, Virgil Palanciuc wrote:
I am assuming in my app. that weak_ptr<>.lock() only requires a "read lock", not a "write lock".. is this true? I've checked out the page at http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/shared_ptr.htm#ThreadSa fety, but there's nothing about weak_ptr there...
Creating and destroying shared_ptr (including those created through weak_ptr::lock) doesn't require any locking at all, as far as the reference counting goes. Unless you are trying to simultaneously access the same weak_ptr/shared_ptr object (rather than copies pointing at the same thing) from different threads? -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAktm8fAACgkQ5vihyNWuA4V1JQCg0rLz8jT5h9ppc0MRxPA7Duwr J5kAnAvt0js3cbBVtQ6E53ePd2XNXE5N =bMMy -----END PGP SIGNATURE-----
participants (4)
-
Frank Mori Hess
-
Peter Dimov
-
strasser@uni-bremen.de
-
Virgil Palanciuc