如何使用互斥量作为成员变量?没有 'simple_encoder' 的复制构造函数被隐式删除

How to use a mutex as a member variable? Without copy constructor of 'simple_encoder' is implicitly deleted

你好,我正在尝试创建一个多线程编码器,它需要一个互斥量,我希望该互斥量成为 class 的成员。但是,我在编译时不断收到:copy constructor of 'simple_encoder' is implicitly deleted because field 'm_mutex' has an inaccessible copy constructor 作为错误消息。经过一个小时的搜索,我找不到我的错误。

请帮帮我,我的构造函数和成员如下所示:

namespace master_thesis
{
class simple_encoder
{
public:

    simple_encoder(uint32_t symbols, uint32_t symbol_size, fifi::api::field field,
                   std::vector<uint8_t> data) :
        m_symbols(symbols), m_symbol_size(symbol_size),
        m_completed(0), m_field(field), m_data(data)
    {

    }
...
private:

    uint32_t m_symbols;
    uint32_t m_symbol_size;
    uint32_t m_completed; 

    fifi::api::field m_field;

    std::mutex m_mutex;

    std::vector<uint8_t> m_data;
    std::vector<std::vector<uint8_t>> m_result;

    std::vector<std::shared_ptr<kodo_rlnc::full_vector_encoder>> m_encoders;
};
}

您的 class 可能包含一个互斥锁作为成员,但是您的 class 会自动成为 non-copyable,因为互斥锁不可复制并且互斥锁现在是您的 class.

因此,无论您在哪里复制 class(在您未向我们展示的代码中),您都不能再这样做了。

出于同样的原因,您的 class 现在也是 non-moveable。

如果这是一个问题,您可以将互斥锁隐藏在共享指针之类的东西后面。但是我会担心共享指针的同步,所以尽量不要...

为了复制包含 mutex 的对象,您必须编写自定义 复制构造函数 复制赋值运算符.

您不需要复制 mutex 来复制对象,因为 mutex 不是对象的 [=27] 的一部分=]value,它只是作为一种保护访问的工具。

复制时,需要使用两个对象的互斥量来保护复制过程中的值成员

例如:

class simple_encoder
{
public:

    simple_encoder() {}

    // copy constructor
    simple_encoder(simple_encoder const& other)
    {
        // no need to lock this objec because no other thread
        // will be using it until after construction
        // but we DO need to lock the other object
        std::unique_lock<std::mutex> lock_other(other.m_mutex);

        // safely copy the data
        m_symbols = other.m_symbols;
        m_symbol_size = other.m_symbol_size;
        m_completed = other.m_completed;

        // ... etc...
    }

    // copy assignment operator
    simple_encoder& operator=(simple_encoder const& other)
    {
        if(&other != this)
        {
            // lock both objects
            std::unique_lock<std::mutex> lock_this(m_mutex, std::defer_lock);
            std::unique_lock<std::mutex> lock_other(other.m_mutex, std::defer_lock);

            // ensure no deadlock
            std::lock(lock_this, lock_other);

            // safely copy the data
            m_symbols = other.m_symbols;
            m_symbol_size = other.m_symbol_size;
            m_completed = other.m_completed;

            // ... etc...
        }

        return *this;
    }

private:
    // value data
    uint32_t m_symbols;
    uint32_t m_symbol_size;
    uint32_t m_completed;

    // non value utility
    mutable std::mutex m_mutex; // needs to be mutable
};

也可以为移动对象编写类似的函数。

如果你有 C++14 你可以使用 std::shared_timed_mutex 并在复制期间锁定 other 对象时替换 std::shared_lock<std::shared_timed_mutex> 应该是更高效。当 moving.

时,你仍然需要 std::unique_lock