CP.22: Never call unknown code while holding a lock (e.g., a callback)
CP.22:永远不要拿着锁调用未知代码(例如callback)
If you don't know what a piece of code does, you are risking deadlock.
如果你不知道一段代码会做什么,就会面临死锁的风险。
Example(实例)
void do_this(Foo* p)
{
lock_guard<mutex> lck {my_mutex};
// ... do something ...
p->act(my_data);
// ...
}
If you don't know what Foo::act does (maybe it is a virtual function invoking a derived class member of a class not yet written), it may call do_this (recursively) and cause a deadlock on my_mutex. Maybe it will lock on a different mutex and not return in a reasonable time, causing delays to any code calling do_this.
如果你不知道Foo::act会做什么(可能这是一个虚函数,会调用某个派生类的成员),它也可能(递归)调用do_this并引发my_mutex发生死锁。它也可能对另外的mutex加锁并无法在合理的时间内返回,从而导致所有调用do_this的代码发生延迟。
Example(示例)
A common example of the "calling unknown code" problem is a call to a function that tries to gain locked access to the same object. Such problem can often be solved by using a recursive_mutex. For example:
调用未知代码引起问题的常见例子是调用的函数试图重新访问一个处于锁定状态的对象。这样的问题通常可以通过使用可重入的recursive_mutex解决。例如:
recursive_mutex my_mutex;
template<typename Action>
void do_something(Action f)
{
unique_lock<recursive_mutex> lck {my_mutex};
// ... do something ...
f(this); // f will do something to *this
// ...
}
If, as it is likely, f() invokes operations on *this, we must make sure that the object's invariant holds before the call.
如果,由于f()可能调用针对*this的操作,我们必须保证调用之前的对象不变式能够维持。
Enforcement(实施建议)
原文链接
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#cp22-never-call-unknown-code-while-holding-a-lock-eg-a-callback