First make generic monitor class. With power of C++11 you can do it as simple as this:
template <class F>
struct FunctionType;
template <class R, class Object, class... Args>
struct FunctionType<R (Object::*)(Args...)> {
typedef R return_type;
};
template <class R, class Object, class... Args>
struct FunctionType<R (Object::*)(Args...) const> {
typedef R return_type;
};
template <class Object_>
class Monitor {
public:
typedef Object_ object_type;
template <class F, class... Args >
typename FunctionType<F>::return_type operation(const F& f, Args... args)
{
critical_section cs;
return (object.*f)(args...);
}
template <class F, class... Args >
typename FunctionType<F>::return_type operation(const F& f, Args... args) const
{
critical_section cs;
return (object.*f)(args...);
}
private:
object_type object;
class critical_section {};
};
Of course critical_section
implementation is up to you. I recommend POSIX or some BOOST.
It is ready to use right now:
Monitor<std::vector<int> > v;
v.operation((void (std::vector<int>::*)(const int&)) &std::vector<int>::push_back, 1);
v.operation((void (std::vector<int>::*)(const int&)) &std::vector<int>::push_back, 2);
size = v.operation(&std::vector<int>::size);
std::cout << size << std::endl;
As you can see sometimes you'll need to explicitly state which member function you want to call - std::vector<> has more than one push_back...
For compilers which still do not support variadic template - the solution without it below - I have time for up to two arguments - it is very inconvenient - if required - add function with more arguments:
template <class F>
struct FunctionType;
template <class R, class Object>
struct FunctionType<R (Object::*)()> {
typedef R return_type;
};
template <class R, class Object>
struct FunctionType<R (Object::*)() const> {
typedef R return_type;
};
template <class R, class Object, class Arg1>
struct FunctionType<R (Object::*)(Arg1)> {
typedef R return_type;
};
template <class R, class Object, class Arg1>
struct FunctionType<R (Object::*)(Arg1) const> {
typedef R return_type;
};
template <class R, class Object, class Arg1, class Arg2>
struct FunctionType<R (Object::*)(Arg1,Arg2)> {
typedef R return_type;
};
template <class R, class Object, class Arg1, class Arg2>
struct FunctionType<R (Object::*)(Arg1,Arg2) const> {
typedef R return_type;
};
template <class Object_>
class Monitor {
public:
typedef Object_ object_type;
template <class F>
typename FunctionType<F>::return_type operation(const F& f)
{
critical_section cs;
return (object.*f)();
}
template <class F>
typename FunctionType<F>::return_type operation(const F& f) const
{
critical_section cs;
return (object.*f)();
}
template <class F, class Arg1>
typename FunctionType<F>::return_type operation(const F& f, Arg1 arg1)
{
critical_section cs;
return (object.*f)(arg1);
}
template <class F, class Arg1>
typename FunctionType<F>::return_type operation(const F& f, Arg1 arg1) const
{
critical_section cs;
return (object.*f)(arg1);
}
template <class F, class Arg1, class Arg2>
typename FunctionType<F>::return_type operation(const F& f, Arg1 arg1, Arg2 arg2)
{
critical_section cs;
return (object.*f)(arg1, arg2);
}
template <class F, class Arg1, class Arg2>
typename FunctionType<F>::return_type operation(const F& f, Arg1 arg1, Arg2 arg2) const
{
critical_section cs;
return (object.*f)(arg1, arg2);
}
private:
object_type object;
class critical_section {};
};