将一个对象和一个互斥锁作为 2 个不同的变量有点容易出错
MyObject myObject;
std::mutex myObjectMutex;
Run Code Online (Sandbox Code Playgroud)
有时我倾向于忘记锁定它。
在 Rust 上,一个共享对象需要在互斥锁中:
std::sync::Mutex<MyObject> mySharedObject
Run Code Online (Sandbox Code Playgroud)
所以我必须这样使用:
mySharedObject.lock().unwrap().objectMethod()
Run Code Online (Sandbox Code Playgroud)
在 C++ 中模拟这样的东西的不太容易出错的方法是什么,所以我不会忘记锁定它?
我想到了一个,std::tuple<std::mutex, MyObject>但它不是很好,我可以忘记锁定。
一种方法是让您Mutex<T>只允许T通过 lambda访问包含的内容:
template <typename T>
class Mutex {
private:
T value;
std::mutex mutex;
public:
// Fill out some constructors, probably some kind of emplacement constructor too.
// For simplicity of the example, this should be okay:
explicit Mutex(T value)
: value(std::move(value))
{}
template <typename F>
auto locked(F&& fn) const& -> std::invoke_result_t<F&&, T const&> {
// Lock the mutex while invoking the function.
// scoped_lock automatically unlocks at the end of the scope
std::scoped_lock lock(mutex);
return std::invoke(std::forward<F>(fn), value);
}
template <typename F>
auto locked(F&& fn) & -> std::invoke_result_t<F&&, T&> {
std::scoped_lock lock(mutex);
return std::invoke(std::forward<F>(fn), value);
}
// Can be worth repeating for const&& and && as well
};
Run Code Online (Sandbox Code Playgroud)
用法:
mySharedObject.locked([] (MyObject& obj) { return obj.objectMethod(); });
Run Code Online (Sandbox Code Playgroud)
仍然可以通过在调用obj内部存储引用.locked(...)并在 外部使用引用来解决这个问题.locked(...),但这几乎需要故意尝试做错误的事情。
另外,请注意,它在 lambda 中可能会受到很大限制,因为常规控制流不再有效(return不从外部范围返回,continue/break不工作等)