Boost logo

Boost :

From: Raoul Gough (RaoulGough_at_[hidden])
Date: 2002-09-30 05:21:39

"Darryl Green" <green_at_[hidden]> wrote on gmane.comp.lib.boost.user
> > From: Raoul Gough [mailto:yg-boost-users_at_[hidden]]
> > Sent: Friday, 27 September 2002 9:44 PM
> > The proxy copy constructor would unlock() the original lock
> > and construct the copy using the original's mutex (which is
> > the part that can't currently work, because there is no
> > public access to a lock's mutex). Assuming that the compiler
> > implements the NRVO, the unlock/lock sequence wouldn't
> > actually happen, and the client code just gets its proxy
> > object constructed for it. If the compiler doesn't implement
> > the NRVO, the code still works, but is less efficient.
> This issue has come up before on the development list (search for
> Boost.Threads Locking Delima). I'm not sure that it was resolved
> satisfactorily - move semantics for scoped_locks seemed to be the
> but I think there were problems actually implementing that. The
intent was
> that if move couldn't be implemented, then the mutex lock methods
would have
> to be exposed.

Hi, Darryl. Thanks for the pointer - move semantics is what I was
looking for. How are things going at tabq?

If anyone is interested, I've come up with an improved proxy
implementation that provides move semantics using the existing
boost::scoped_lock. It stores its own reference to the original mutex,
which is only slightly less efficient than if scoped_lock had move
semantics itself. This allows code like the following:

void foo (mt::holder<std::deque<int> > &queue)
  queue()->push_back (5); // thread-safe

Raoul Gough.

// Proxy template
#include <boost/thread/mutex.hpp>

namespace mt
  template<typename T>
  class proxy
    boost::mutex &mMutex;
    boost::mutex::scoped_lock mLock;
    T *mPtr;

    boost::mutex &release ()
      return mMutex;

    proxy (proxy &other)
      : mMutex (other.release())
      , mLock (mMutex)
      , mPtr (other.mPtr)

    template<typename TOwner> proxy (TOwner &owner)
      : mMutex (owner.mutex())
      , mLock (mMutex)
      , mPtr (&

    T *get() const { return mPtr; }
    T &operator* () const { return *mPtr; }
    T *operator-> () const { return mPtr; }

// Holder with thread-safe proxy access:

#include "proxy.hh"
#include <boost/thread/mutex.hpp>

namespace mt
  template<typename T>
  class holder
    template<typename X> friend class proxy;

    typedef proxy<T> proxy_type;
    typedef proxy<T> returnable_proxy_type;

    holder () : mMutex (), mT () { }
    explicit holder (T const &t) : mMutex (), mT (t) { }

    returnable_proxy_type operator() ();
    // Convenience function. It is more efficient for the caller
    // to construct a proxy<T> directly from the holder object.

    // Proxy support methods. These allow a proxy<T> to construct
    // itself from us (accessible via friendship).
    boost::mutex &mutex () { return mMutex; }
    T &data () { return mT; }

    boost::mutex mMutex;
    T mT;

  template<typename T>
  typename holder<T>::returnable_proxy_type
  holder<T>::operator() ()
    returnable_proxy_type temp (*this);
    return temp;

Boost list run by bdawes at, gregod at, cpdaniel at, john at