我有一个ConcurrentQueue
类,它基于用户提供的容器,并带有这样的构造函数...
ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue) {}
但是,我需要在复制时锁定other
的互斥锁。
选项1:
所以我根本无法使用复制构造函数,并且......
ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue)
{
std::lock_guard<std::mutex> lock(other.m_Mutex);
m_Queue = other.m_Queue;
}
但我不能保证复制分配和复制构造是等效的功能。
选项2:
我可以有私人方法......
std::queue<T, Container> GetQueue() const
{
std::lock_guard<std::mutex> lock(other.m_Mutex);
return m_Queue;
}
然后在构造函数中执行此操作...
ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.GetQueue()) {}
但是这可能(取决于优化)使用m_Queue的复制构造函数一次,它移动构造函数一次。我也不能保证副本和移动只相当于副本。此外,用户提供的容器可能是奇怪的并且可以复制但不可移动,这也会导致这种方法出现问题。
那么,我该怎么办?
答案 0 :(得分:9)
ConcurrrentQueue::ConcurrrentQueue(
ConcurrrentQueue const& other )
: m_Queue( (std::lock_guard<std::mutex>( other.m_Mutex ),
other.m_Queue ) )
{
}
应该有用。
答案 1 :(得分:1)
锁定,创建内容的副本,然后将其与成员交换。至少那是最简单和恕我直言最干净的方式。另一种不太干净的方法是使用逗号运算符:(a, b)
产生b
,但如果a
是一个范围锁定,临时将生效到下一个序列点,即直到你使用b
初始化您的本地副本。
那就是说,有两件事需要考虑: