Way*_*eng 6 c++ templates mutex lock-guard
有一个类模板Foo<T>。对于某些特定类型,函数应该使用lock_guard. 这是示例代码:
#include <type_traits>
#include <mutex>
#include <vector>
template<typename T>
class Foo {
public:
void do_something(int k) {
if constexpr(std::is_same_v<T, NeedMutexType>) {
std::lock_guard<std::mutex> lock(mtx_);
}
resource_.push_back(k);
// code for task with resource_ ...
}
private:
std::mutex mtx_;
std::vector<int> resource_;
};
Run Code Online (Sandbox Code Playgroud)
将会std::lock_guard在 if constexpr 范围的末尾被破坏。(如果不正确,请纠正。)
为了处理这个问题,我可以将下面的任务代码复制resource_到 if constexpr 范围中,或者只使用原始的,std::mutex例如mtx_.lock()& mtx_.unlock()。
有什么方法可以处理这个问题std::lock_guard吗?谢谢。
只需在解锁状态下构造锁,然后再将其锁定:
template<typename T>
class Foo {
public:
void do_something(int k) {
std::unique_lock<std::mutex> lock(mutex_, std::defer_lock);
if constexpr(std::is_same_v<T, NeedMutexType>) {
lock.lock();
}
resource_.push_back(k);
// code for task with resource_ ...
}
private:
std::mutex mtx_;
std::vector<int> resource_;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您需要std::unique_lock为此使用,因为std::lock_guard无法解锁构建
如果您需要经常做这种事情,也许std::conditional可以在这里救援。
template<class Mutex>
struct FakeLockGuard { FakeLockGuard(Mutex&){} };
template<typename T, class Mutex = std::mutex>
using OptionalLock = typename std::conditional<
std::is_same_v<T, NeedMutexType>,
std::lock_guard<Mutex>,
FakeLockGuard<Mutex>>::type;
Run Code Online (Sandbox Code Playgroud)
在这里,我们定义了一个不执行任何操作的类模板,其构造方式与std::lock_guard. 然后,我们使用 withstd::conditional来选择 或std::lock_guard,FakeLockGuard具体取决于类型检查的结果。
现在您可以按如下方式使用它:
template<typename T>
class Foo {
public:
void do_something(int k)
{
OptionalLock<T> lock(mtx_);
resource_.push_back(k);
// ...
}
private:
std::mutex mtx_;
std::vector<int> resource_;
};
Run Code Online (Sandbox Code Playgroud)
您可以通过在构造函数中设置断点FakeLockGuard或使其输出某些内容来轻松验证其是否有效。
这就是如何让它在编译时工作。但我认为正如您已经提到的,您可以简单地构造 a unique_lock,然后有条件地锁定它。这样做的好处是让任何需要使用你的代码的人都更加清楚。最后,就看你认为最合适的了。
| 归档时间: |
|
| 查看次数: |
249 次 |
| 最近记录: |