Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
187 views
in Technique[技术] by (71.8m points)

c++ - How to wrap calls of every member function of a class in C++11?

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";
});
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...