ハーブサッターは約C++ 11と同時実行性(this videoを参照)C++ 11でクラスのすべてのメンバー関数の呼び出しをラップする方法は?
ここで重要な考え方は、すべての関数呼び出しのロックが解除されているロックが飾られるべき非ロッククラスX
を持つことがある話でこの質問をしました機能の後に。
しかし、Herb Sutterはドリフトして、ファンクタベースのアプローチを提示します。 C++ 11では、各関数呼び出しを包括的にクラスのロックとロック解除でラップすることも可能ですか(手動ですべての関数呼び出しをラップするのではないかと思います)。
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...
};
Decoratorパターン
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;
};
もありますが、この可能性のようなものがあります:
template<>
class wrap_everything;
wrap_everything<X> x;
x.somefunc(x1,x2,...); // this is then locked.
完全性のために、これはハーブサッターのファンクタベースのアプローチです:
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";
});
少なくともコンパイラ(gccなど)では、コンパイラはコードを変更しなくてもこれを実行できます。通常はプロファイリングに使用されますが、各関数呼び出しの前後に指定された関数への呼び出しを挿入することができます。あなたがロックを必要とする場所と実際には行っていない場所を整理するためのコードでは、それほど些細なことはありません。 –
@JerryCoffin私はこれは、すべてのメンテナーがコード以外の場所でロックを探すのは致命的だと思います。 – Alex
@Alex大きな質問です。あなたが言うように、SutterがC++とBeyond 2012でこのことを覚えてから、それをやり直したのを覚えています。多分、彼はC++ 14のフィーチャセットのヒントを捨てていたかもしれません。 –