Herb Sutter asked this question in a talk about C++11 and concurrency (See this video)
The key idea here is to have a non locking class X
where every function call should be decorated with a lock that is unlocked after a function.
However, Herb Sutter drifts then off and presents a functor based approach. I'm wondering if it is even possible with C++11 to wrap each function call with lock and unlock of a class in a generic way (not wrapping every function call manually).
class X { public: X() = default; void somefunc(arg1 x1, arg2 x2, ...); void somefunc2(arg1 x1, arg2 x2, ...); /* and more */ }; // herb admits one way to make all functions *available* // in another class is by derivation class XX : public X { public: XX() = default; // all functions available in NON overloaded form... };
there is also the decorator pattern
class XXX { public: XXX(X &x) : m_x(x) {} // explicitly call each wrapped function ... done for each class separately. void somefunc(arg1 x1, arg2 x2, ...); void somefunc2(arg1 x1, arg2 x2, ...); private: class X& m_x; };
but is there something like this possible:
template<> class wrap_everything; wrap_everything<X> x; x.somefunc(x1,x2,...); // this is then locked.
for the sake of completeness this is herb sutter's functor based approach:
template <class T> class locker { private: mutable T m_t; mutable std::mutex m_m; public: locker( T t = T{} ) : m_t(t) {} template <typename F> auto operator()(F f) const -> decltype(f(m_t)) { std::lock_guard<mutex> _{m_m}; return f(t); } }; // usage locker<std::string> s; s([](string &s) { s += "foobar"; s += "barfoo"; });
A wrapper function is a subroutine (another word for a function) in a software library or a computer program whose main purpose is to call a second subroutine or a system call with little or no additional computation.
A member function is declared and defined in the class and called using the object of the class. A member function is declared in the class but defined outside the class and is called using the object of the class.
When people write a wrapper, then, they are doing something like this: class int_ptr_wrapper { public: int_ptr_wrapper(int value = 0) : mInt(new int(value)) {} // note! needs copy-constructor and copy-assignment operator! ~int_ptr_wrapper() { delete mInt; } private: int* mInt; };
It is the process or method to contain the information. Wrapping of data and function into a single unit is called data encapsulation. Encapsulation is a method to hide the data in a single entity or unit along with a method to protect information from outside. It can be implemented using by access modifier.
The question is about the EXECUTE-AROUND pattern. I made a generic (but only barely tested) implementation of EXECUTE-AROUND POINTER at https://gitlab.com/redistd/redistd/blob/master/include/redi/exec_around.h
This allows:
struct X { void f() { } }; auto x = mutex_around<X>(); x->f(); // locks a mutex for duration of call to X::f
A more in depth explaination on how the family of execute around patterns work can be found here (pdf)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With