Is it safe to return by value a shared_ptr that is guarded by mutex?
Here is a code sample:
class A {
boost::mutex a_mutex;
boost::shared_ptr<int> a;
boost::shared_ptr<int> clone_a(void) {
boost::lock_guard<boost::mutex> lock(a_mutex);
return a;
}
};
The suggestion is that the boost::shared_ptr
copy constructor call on A::a
will precede the boost::lock_guard
destructor call despite of the compi开发者_开发知识库ler optimizations.
So, is it safe to call A::clone_a()
?
If by "safe" you mean you won't get data races on a
, then yes. It is exactly as you say.
However, it won't protect further accesses to *a
(or *clone_a()
), as you probably know. I'm not sure, why is the method called "clone", as it doesn't clone anything.
Yes, this code is safe. If you refer to shread_ptr Thread-Safety you can see that threaded write access to thread-local shared_ptr objects is just fine.
In your code above the access to the member shared_ptr requires the lock, since it could be accessed by multiple threads. The copy to the return temporary is done within the lock, thus you're safe there. That temporary cannot be seen by other threads so at that point you are safe to copy it to other shared_ptr's.
Now perhaps the choice of clone_a
as a function name is wrong. You aren't cloning the underlying object, you are simply getting a copy of the shared_ptr. So I am assuming you intend on sharing the same underlying "int".
Not if you use the return value. The return value itself is a
temporary, whose lifetime extends beyond the end of the function; it
will be destructed at the end of the full expression which calls
A::clone_a
. So if you write something like:
shared_ptr<int> newA = object->clone_a();
, the formal semantics will be for the temporary returned by
object->clone_a()
to be copied into newA
, in the context of the
caller (and so unprotected by the mutex). In this particular case, you
may get away with it because of RVO, but that won't necessarily be the
case, and there are other cases where RVO can't intervene.
If all you're worried about is the copy of the pointer, I'm pretty sure
that if you set the right compiler options (-D
somthing
), boost::shared_ptr
will behave atomically. In
this case, you don't need the mutex at all.
精彩评论