|
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