如何将包含对象的互斥体从一个函数传输到另一个函数?

Jer*_*rry 1 c++ multithreading design-patterns

#include <mutex>

class ConcurrentQueue {
    // This class contains a queue and contains functions push to the queue and pop from the queue done in a thread safe manner.
    std::mutex m;
};

class Producer {
    // This class contains several methods which take some ConcurrentQueue objects and then schedule tasks onto it.
public:
    void func(ConcurrentQueue a) {}
};

class Consumer {
    // This class contains several methods which take the same ConcurrentQueue objects and then remove the tasks and complete them one by one.
public:
    void func(ConcurrentQueue a) {}
};

int main() {
    // Here I want to generate the necessary ConcurrentQueue objects and then start threads for producer and consumer methods where I supply it with the required queue objects.
    ConcurrentQueue a;
    Producer b;

    // :( Unfortunately I cannot pass in any of my ConcurrentQueue objects to the methods as apparantly I cannot copy transfer a mutex.
    b.func(a); // This line gives compiler error saying the copy constructor is deleted.
    
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码通过注释说明了整个情况。我如何更好地设计它才能实现这一目标?

Jer*_*ner 5

如果您不希望 ConcurrentQueue 类可复制,则不要按值传递它;请改用引用传递(即类型const ConcurrentQueue &或的参数ConcurrentQueue &)。

OTOH 如果您确实希望您的 ConcurrentQueue 类是可复制的(并且您应该仔细考虑允许复制 ConcurrentQueue 对象是否对您的目标有帮助或有害),您可以简单地向您的 ConcurrentQueue 类添加一个复制构造函数复制其他成员变量,但不尝试复制 std::mutex:

class ConcurrentQueue {
    // This class contains a queue and contains functions push to the queue and pop from the queue done in a thread safe manner.
    std::mutex m;
    std::queue<int> q;

public:
    ConcurrentQueue()
    {
       // default constructor
    }

    ConcurrentQueue(const ConcurrentQueue & rhs)
    {
       // serialize access to rhs.q so we can read its 
       // contents safely while copying them into this->q
       const std::lock_guard<std::mutex> lock(const_cast<std::mutex &>(rhs.m));
       q = rhs.q;
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,我还需要添加一个默认构造函数,因为一旦您向类添加任何类型的构造函数,编译器将不再自动为您创建默认构造函数。如果您使用的是 C++11 或更高版本,则可以改为通过声明默认构造函数ConcurrentQueue() = default;