香草萨特问谈谈这个问题,关于C++ 11和并发性(见this video)如何在C++ 11中封装类的每个成员函数的调用?
这里的关键思想是有一个非锁定类X
,每一个函数调用应该用锁解锁装饰功能后。
然而,草药萨特然后漂移,并提出了基于函子的方法。我想知道用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...
};
也有装饰图案
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功能集。 –