Aschwin Gopalan said:
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.
Sure it is, and this is what will be supplied in the next release. You have to create a "null_mutex" type (I need a better name) that has scoped_lock's that do nothing. This is similar to what you have below, but applied to a new mutex type instead of your policy base type.
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
Why is this "not nice"? The syntax is similar to current ScopedLock types.
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.
I can't explain it, mostly because the code you posted can't be what you're really using. You reference an m_pmutex when the only member is m_mutex and is not the pointer type the construction would indicate it should be.
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)
Not sure I have an answer here for the same reason.
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
I'm working on something similar for the next release. Here's a synopsis
of the idea:
class foo : public boost::syncrhonized