Boost logo

Boost :

From: Beman Dawes (beman_at_[hidden])
Date: 2000-08-22 07:01:39


Greg Colvin wrote:

> ...
>
>Another possibility, which I think Beman already suggested, is to
>expose the mutex as a smart pointer class with an operator-> that
>handles the locking.

Here is an example of the member function wrapping trick from Bjarne.

I put together this little experiment to see how it might apply to a
monitor. There is probably a way to do it where call_proxy holds a single
pointer, but I was just hacking so didn't try for optimal code.

I've tested it only with VC++, which works correctly, producing the output:

   lock
   f() called
   unlock

--Beman

// experiment with member function wrappers

// see C++ Report, June, 2000, Bjarne Stroustrup, Wrapping C++
// Member Function Calls

#include <iostream>
using std::cout;

// just for testing, say this is the MT primitive we want to guard
// each monitor call

struct mt_primitive
{
   void lock() { cout << "lock\n"; }
   void unlock() { cout << "unlock\n"; }
};

// call_proxy helper template used to call unlock()

template< class T > class monitor;

template< class T >
class call_proxy {
   T * p;
   mt_primitive & mtp;
   mutable bool own;
  public: // VC++ workaround; monitor should be a friend.
// template<class T> friend class monitor;
        call_proxy(T* pp, mt_primitive & mtpr) :p(pp), mtp(mtpr), own(true) {
} // restrict creation
        call_proxy& operator=(const call_proxy&); // prevent assignment
  public:

        call_proxy(const call_proxy& a)
                : p(a.p), mtp(a.mtp), own(true) { a.own=false; }

        ~call_proxy() { if (own) mtp.unlock(); }

        T* operator->() /*const*/ { return p; }
};

// monitor class template guards base class member function calls
// via calls to lock() and unlock()

template< class T >
class monitor : protected T {
   mt_primitive monitor_primitive;
public:
   call_proxy<T> operator->() //const
   {
     monitor_primitive.lock();
     return call_proxy<T>(this, monitor_primitive);
   }
};

// UserType with a function f() we want to guard

struct UserType { void f() { cout << "f() called\n"; } };

// main

int main()
{
   monitor<UserType> mon;

   mon->f(); // calls lock(), f(), unlock()

// mon.f(); // compile error: not accessible

   return 0;
}

--- end ---


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