问题描述
template <typename T>
T acquireLock(std::mutex& _lock,const std::function<T()>& execution) {
try {
std::lock_guard<std::mutex> mutex (_lock);
return execution();
} catch (std::logic_error& error) {
std::cerr << "[exception caught]\n\t" << error.what() << std::endl;
}
return false;
}
class MyThreadSafeClass {
public:
bool Init();
bool StopApi();
unsigned int GetValue() {
auto ret = acquireLock<unsigned int>(_lock,[this]() -> unsigned int {
// does some work that's not thread-safe...
return value;
});
return ret;
}
private:
bool _ready = false;
std::mutex _lock;
};
我的疑问是,每当我看着GetValue()
方法调用acquireLock()
时,execution()
调用是否也会受到锁定范围的影响?
auto myClass = new MyThreadSafeClass();
myClass->GetValue();
着眼于this,
创建一个lock_guard对象时,它将尝试获得该对象的所有权 给出的互斥量。当控制权离开了 已创建lock_guard对象,销毁了lock_guard,并且 互斥锁被释放。
我仍然不清楚execution()
代码内部发生的事情是否仍受锁定范围的影响。
解决方法
- 由return语句的操作数建立的全表达式结束时,对调用结果的复制初始化在临时变量销毁之前进行排序,而该语句又在销毁局部变量之前进行排序([stmt.jump])包含return语句的块。
所以我们得到:
- 互斥锁已锁定 按住锁时会调用
-
execution()
- 锁已释放
- 求值返回给调用者(或输入
catch
子句)
换句话说,它将按预期工作。
不相关的注释:std::function
效率不高。模板化可调用类型应该更好:
template<typename F>
auto doLocked(std::mutex& _lock,F const& f) -> decltype(f()) {
std::lock_guard<std::mutex> lock(_lock);
return f();
}