Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2000-01-06 16:03:11


From: Andy Glew <glew_at_[hidden]>

> A challenge:
>
> It sure would be nice if we could write, in C++, a template
> mutexed<T>
> that ensured full mutually exclusion for any arbitrary type T.
> That did not have to know about the methods of T.
>
> I was about to start my usual moaning about C++ not really
> allowing transparent proxying - to fully proxy something in C++
> you need to enumerate all of its methods - but I think that we might
> be able to come close.
>
> Here's a stab at it using some helper macros. (Yeah, well, I hope
> that someone can eliminate the macros.)
>
I will try to do so below ;)

> template<typename T>
> class mutexed {
> private:
> lock_t lockvar; // any lock you want - I'll assume just a lock bit
> // handled by primitive processor instructions
> T value;
> public:
> void acquire_lock() { lock.acquire_lock(); }
> void release_lock() { lock.release_lock(); }
> public:
> // constructors don't require locks on constructee
> mutexed() :
> lock(0), // default unlocked
> value() // must have a default constructor;
> // must be constructible without locking
> {}
> mutexed(const mutexed& from) :
> lock(0),
> value()
> {
> from.lock.acquire_lock();
> this->value = from.value;
> from.lock.release_lock();
> // or, use constructor locking, if you want locks released on
exceptions
> }
> public:
> // assignment requires locks on both sides
> T& operator=(mutexed<T>& rhs) {
> assert(this->lock);
> { rhs.lock.acquire_lock();
> this->value = rhs.value;
> rhs.lock.release_lock();
> // or, use constructor locking, if you want locks released on
exceptions
> }
> }
> public:
> // destructor - checks lock?
> ~mutexed() {
> assert(lock == 0); // your choice
> }
> public:
> // only allow access via ->
> // which checks lock
> // (if I could have -> enforce lock, I'd use that)
> T* operator->() {
> assert(lock);
> return this;
> }
> };
>
>
[snip]
> I was hoping that you could do just
>
> mutexed<T> mobj;
> mobj->method(); // implicitly mutexed
>
> although I don't see how to do this
>

You can achive this, if you implement auto_lock<> template like this:

template<class T>
class auto_lock {
  public:
    auto_lock( mutexed<T>& ref )
      : mutexed_ref_( ref )
      { mutexed_ref_.lock.acquire_lock(); }

    ~auto_lock() { mutexed_ref_.lock.release_lock(); }

    T* operator ->() const { return &mutexed_ref_.value; }

  private:
    mutexed<T>& mutexed_ref_;
};

and change the implementation of mutexed<T>::operator->() to something like:

template<typename T>
class mutexed {
....
public:
    auto_lock<T> operator->() {
        assert(lock);
        return auto_lock<T>( *this );
    }
};

and now this must (??) work:

mutexed<T> mobj;
mobj->method(); // *is* implicitly mutexed

-Alexy


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk