
Hello!
I have a small class that I would like to get some feedback on. If you
have the time. =)
What I would like to do is to protect an instance of some class T with a
mutex. It seems to me that I would be able to do this with a smart
pointer that returns a proxy class, from operator->(), that locks a
mutex in its constructor and unlocks it in its destrcutor. This is my
intitial implementation of such a class:
#include

On Thu, September 7, 2006 8:38 am, Mattias Brändström wrote:
What I would like to do is to protect an instance of some class T with a mutex. It seems to me that I would be able to do this with a smart pointer that returns a proxy class, from operator->(), that locks a mutex in its constructor and unlocks it in its destrcutor.
I've played with this thought several times in the past. In the end, what made me never implement it is the fact that it locks and unlocks the mutex for every single operation on the class. If you call more than one operation in sequence, that's not exactly efficient. That said, for classes that have only operations which you usually don't call in sequence, the pointer is quite useful. I have just one change: there is no reason to allocate the lock dynamically.
class LockProxy { public: LockProxy(boost::shared_ptr<T> p, boost::shared_ptrboost::recursive_mutex mutex) : p_(p), lock_(*mutex) { }
const boost::shared_ptr<T> &operator->() { return p_; }
private: boost::shared_ptr<T> p_; boost::recursive_mutex::scoped_lock lock_; };
I've also changed the return type of operator ->. There's no need to create a copy of the shared_ptr.
What do you think? Would this work? Would this be equivalent to locking a member mutex in each method of T (as long as all calls to an instance of T is invoked via the same LockPointer)?
I'm not entirely sure when the temporary will be destroyed, but if I remember D&E correctly, then it will work.
For some reason this is the kind of thing I would expect to find in boost, but I have not been able to. Have I missed some part of boost that I should know about?
No, there is no such thing in Boost. The reason is probably the limited set of use cases for the pointer. Sebastian Redl

Sebastian Redl wrote:
On Thu, September 7, 2006 8:38 am, Mattias Brändström wrote: I've played with this thought several times in the past. In the end, what made me never implement it is the fact that it locks and unlocks the mutex for every single operation on the class. If you call more than one operation in sequence, that's not exactly efficient. That said, for classes that have only operations which you usually don't call in sequence, the pointer is quite useful. I have just one change: there is no reason to allocate the lock dynamically.
For some reason most of my classes that ar thread safe handles locking in a similar way to the LockPointer, locking a mutex for each method call. I don't like exposing the thread safety so to speak. But I can definitely see your point in that being inefficient some times. Another small thing I have come to think of is the case where the pointed to class call itself as a result of a method call thru thru the lock pointer. In these cases a second lock will not be created as it would if I had implemented locking within the class itself. However, I can't think of any cases where this will cause any problems.
class LockProxy { public: LockProxy(boost::shared_ptr<T> p, boost::shared_ptrboost::recursive_mutex mutex) : p_(p), lock_(*mutex) { }
const boost::shared_ptr<T> &operator->() { return p_; }
private: boost::shared_ptr<T> p_; boost::recursive_mutex::scoped_lock lock_; };
I've also changed the return type of operator ->. There's no need to create a copy of the shared_ptr.
I'll use these changes in my implementation. :.:: mattias

Mattias Brändström wrote:
Sebastian Redl wrote: [snip]
class LockProxy { public: LockProxy(boost::shared_ptr<T> p, boost::shared_ptrboost::recursive_mutex mutex) : p_(p), lock_(*mutex) { }
const boost::shared_ptr<T> &operator->() { return p_; }
private: boost::shared_ptr<T> p_; boost::recursive_mutex::scoped_lock lock_; };
I've also changed the return type of operator ->. There's no need to create a copy of the shared_ptr.
I'll use these changes in my implementation.
Actually, it seems that I will not be able to have the lock as member of LockProxy since it's boost::noncopyable. LockPointer's operator->() returns a LockProxy by value and needs to copy all member of it to do so. I can't see any way around this so I need to have a pointer to the lock in LockProxy. Perhaps someone else can see a way to not have to use a pointer to the lock? :.:: mattias
participants (3)
-
Mattias Brandstrom
-
Mattias Brändström
-
Sebastian Redl