Boost logo

Boost :

From: William Kempf (sirwillard_at_[hidden])
Date: 2000-08-22 14:53:45


--- In boost_at_[hidden], jsiek_at_l... wrote:
>
> This brings up an issue with our Mutex design... currently the
scoped
> lock object is the only way to access the lock/unlock functionality.
> This wrapper technique needs access to lock/unlock. Perhaps we
should
> make lock/unlock a protected member. This wrapper could then gain
> access through subclassing. This essentially makes lock/unlock a
part
> of the "public" interface, though it gives a warning to users.
>
> (note that if we have a lock() function we have to change the name
of
> the lock type to something else, or vice versa)

Here's an implementation that works on top of the Win32
implementation of our models that I've posted. It works fine with
our Mutex and MutexLock models. I would not recommend this
particular design, but a concept along these lines would be
appropriate. (The big flaw I have with this design is that the mutex
is external to the class, while I think it should be internal,
especially if the class is to be designed with CVs in mind.)

#include <iostream>

using namespace std;

template <typename T, typename L>
class call_proxy
{
public:
        call_proxy(T* obj, L& mutex) : m_obj(obj), m_lock(new L::lock
(mutex)) { }
        call_proxy(call_proxy& proxy)
                : m_obj(proxy.m_obj), m_lock(proxy.m_lock)
                { proxy.m_lock = 0; }
        ~call_proxy() { delete m_lock; }

        T* operator->() { return m_obj; }

private:
        T* m_obj;
        L::lock* m_lock;
};

template <typename T, typename L=boost::mutex>
class monitor : protected T
{
public:
        call_proxy<T, L> operator->() { return call_proxy<T, L>(this,
m_mutex); }

private:
        L m_mutex;
};

class null_mutex
{
public:
        class lock
        {
        public:
                lock(null_mutex&) { cout << "lock" << endl; }
                ~lock() { cout << "unlock" << endl; }
        };
};

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

int test_monitor()
{
        monitor<UserType, null_mutex> mon;
        mon->f();
// mon.f();
        return 0;
}

The use of the heap here may lead to heap fragmentation, not to
mention the runtime overhead, and so it isn't the optimal solution.
Making call_proxy a friend may be a better solution, I just wanted to
show that it could be done and that it even could be done with out a
friend declaration. I'm not in favor of making lock/unlock methods
in the public interface of Mutex.

Bill Kempf


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