如何在 C++ 中模拟 Rust 的 Mutex<Object>?

Raf*_*elo 7 c++ rust

将一个对象和一个互斥锁作为 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>但它不是很好,我可以忘记锁定。

Jus*_*tin 6

一种方法是让您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不工作等)