Dear Boosters!
I am designing a class template with policy controled threading
behaviour, like
template
class Something;
where there are different ThreadingModels available (see Modern C++
Design by Alexandrescu for a discussion of policies).
I would like to have Something to inherit ThreadingModel. The idea is
that SingleThreaded does not impose any additional penalties. So my Idea
was to have something like
class SingleThreaded
{
public:
void lock() {}
void release() {}
}
class MultiThreaded
{
public:
void lock() { lock_mutex(m_mutex) }
void release() { release_mutex(m_mutex) }
private:
mutex m_mutex;
}
and have all functions call lock() and release() accordingly.
But this is not good, since it does not use Resource Initialization is
Aquisition and leads to exeption safety problems and so on. Furthermore,
it is not (because of these reasons) possible to model using
boost::mutex ´es since they do not expose a lock() release() interface
but can only be locked using scoped_locks.
So another idea is to have something like
class SingleThreaded
{
class scoped_lock
{
// Empty class
}
}
class MultiThreaded
{
public:
class scoped_lock
{
scoped_lock() // constructor that locks m_mutex of
// of MultiThreaded
~scoped_lock() // unlocks
}
private:
boost::mutex m_mutex;
}
and have the member functions lock the mutex by instantiating
an embeded scoped_lock object.
Now there are some questions I have:
1.) Does this approach sound sensible, or am I overlooking a commonly
used Idiom to achieve this functionality
2.) How can I access the m_mutex member of the right object in
scoped_lock()? The only way I can imagin is to give the this pointer
to the constructor (like scoped_lock lock(this);). It is somehow
not nice, but possible
3.) The actual code I am using looks like
//! Policy class.
/*! Multithreading, object operations are synchronized via
* a non-recursive lock, obeying strict Resource Acuisition is
Initialization
* semantics
*/
class LockDefault
{
public:
LockDefault() :
m_pmutex(new boost::mutex)
{
}
class scoped_lock : public boost::mutex::scoped_lock
{
public:
scoped_lock(LockDefault &obj) :
boost::mutex::scoped_lock(obj->m_pmutex)
{ }
~scoped_lock() { }
};
public:
boost::mutex m_mutex;
};
This works with gcc and I think it does what it should. It
fails to compile with VC++6 giving
error C2512: 'scoped_lock<class boost::recursive_mutex>' : no
appropriate default constructor
which I do not understand, since the default constructor is never
called.
Also, I do not like to have the mutex member public, but if I make
it private and write
friend class scoped_lock;
this does not have the desired effect (MSVC still complains about
private data member access)
Somehow, I must be getting something completely wrong, so
if somebody could point me in the right direction, I would be thankful.
BTW: I am using boost_1_30_0
Thanks,
Aki