Re: [boost] Serious problem with gcc 4 on Mac OS X, when using boost:shared_ptr

Peter Dimov Wrote:
Ananda Tallur wrote:
Hello,
Originally, I had discovered a problem when using boost::unit_test_framework, for which I have already posted. But, by further analysing the problem, I could come out to a simple program, using only boost shared pointers, and which fails : -> on Mac OS X 10.4 -> when compiled with gcc 4.0.1 (coming with XCode 2.2.1), or gcc 4.1 (delivered by darwin ports) -> with optimisations : at least -O, or -O1, or -O2,etc... It works correctly with -O0 -> using either boost 1.33.1, 1.33.0, or 1.32.0
Below is the sample test program :
--- macosx_gcc4problem.cpp ---
[...]
This issue has already been reported, along with a fix, by Howard Hinnant:
http://lists.boost.org/Archives/boost/2006/03/102088.php http://lists.boost.org/Archives/boost/2006/03/102122.php http://lists.boost.org/Archives/boost/2006/03/102134.php
and the upcoming 1.34 release will no longer suffer from it.
Thank you very much for taking the time to simplify the failing example. I've reformatted it a bit as a test case. If you verify that it still fails for you, I'll include it in the regression tests.
#include <boost/shared_ptr.hpp> #include <boost/detail/lightweight_test.hpp>
struct A { int value; };
struct B { B( boost::shared_ptr<A> val ): a( val ) {}
boost::shared_ptr<A> a; };
struct C { C( B val ): b( val ) {}
B b; };
struct D { D( C val ): c( val ) {}
C c; };
D create() { boost::shared_ptr <A> a( new A );
a->value = 12345;
return D( C( B( a ) ) ); }
int main() { D d = create();
BOOST_TEST( d.c.b.a->value == 12345 );
return boost::report_errors(); }
Hello Peter, Thank you very much, this is very good news to know that the problem has already been fixed ! I have checked the reformatted test program just above, and confirm that : - It does not work for me (gcc 4.0.1 on Mac OS X, ppc G5), when compiled with optimization. - Once patched the file sp_counted_base_gcc_ppc.hpp including modifications from cvs, the problem disappears, and the test passes with success, with or without optimization. So the test program does its job, Thank you again Anand

By default shared_ptr is now compiled to be non thread safe (I could be wrong here, I am confused by all of the conflicting comments I have seen). It is also compiled this why in my local version. It seems that the delete/cleanup is the only problem since the reference count seems to be wrapped into a atomic function. Since I really cannot control the deletion/going out of scope of the pointers, is shared_ptr any use in a threaded application? I was looking to see if writing my own "deleter" would solve this program (one that I could make it thread safe), but it looks like this gets called after the part where it is determined if the deleter should be called. So what are your choices if you are multithreaded? __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

By default shared_ptr is now compiled to be non thread safe (I could be wrong here, I am confused by all of the conflicting comments I have seen).
No the pointer itself is always thread safe if it's possible to make it so, the thing it points to is not thread safe unless you choose to make it so.
It is also compiled this why in my local version. It seems that the delete/cleanup is the only problem since the reference count seems to be wrapped into a atomic function. Since I really cannot control the deletion/going out of scope of the pointers, is shared_ptr any use in a threaded application? I was looking to see if writing my own "deleter" would solve this program (one that I could make it thread safe), but it looks like this gets called after the part where it is determined if the deleter should be called.
I don't understand what you are asking here: of course the deleter is thread safe: if the reference count is handled by atomic operations (ie thread safe), then when the count reaches zero *there is only one thread left observing the pointer* so deletion is necessarily thread safe. Note that I'm assuming there is no thread trying to copy the shared_ptr at the same time as it's destructor is being called by second thread: that would be a design error if it occurred! What that means in practice is you can: 1) Create a shared_ptr to a const object, and safely pass that object around between threads, and access both the pointer and the immutable object to which it points from whatever threads you want. *As long as there is no thread that has a mutable pointer to the object*. 2) Create a class that uses the pimpl idiom and copy-on-write in an entirely thread safe manner: all mutating operations will be preceded by a copy operation leading to a thread-local copy of the original object. While non-mutating operations may safely use shared access to the same underlying object. While you can *not* do: 1) Have multiple threads accessing the object *pointed to* a shared_ptr if any of those threads mutate the object. In this case you would need a separate mutex to govern all accesses to the object (*both read and write*), this is *in addition to* the thread safety guarantees offered by shared_ptr. And finally: while it is technically possible to create a smart pointer that "monitors" all access to the object to which it points - for example making all accesses thread safe - such smart pointers have a more restricted interface than shared_ptr, and are typically needlessly inefficient compared to a separate mutex (think multiple accesses chained together). Whew. If that's not clear enough don't write multithreaded code :-) Honestly shared_ptr analysis is easy compared to most concurrent problems (so here's hoping I haven't made any stupid mistakes in the above!) John.

Paul Joseph Panaro wrote:
By default shared_ptr is now compiled to be non thread safe (I could be wrong here, I am confused by all of the conflicting comments I have seen).
Have you read http://boost.org/libs/smart_ptr/shared_ptr.htm#ThreadSafety ?
participants (4)
-
Ananda Tallur
-
John Maddock
-
Paul Joseph Panaro
-
Peter Dimov