简体   繁体   English

如何在初始化列表中锁定互斥锁?

[英]How can I lock a mutex in an initializer list?

I have a ConcurrentQueue class that is based around a user provided container with a constructor like this... 我有一个ConcurrentQueue类,它基于用户提供的容器,带有这样的构造函数...

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue) {}

But, I need to lock other 's mutex while it's being copied. 但是,我需要在复制时锁定other的互斥锁。

Option 1: 选项1:

So I could not use the copy constructor at all, and do... 所以我根本不能使用复制构造函数,并且......

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue)
{
    std::lock_guard<std::mutex> lock(other.m_Mutex);
    m_Queue = other.m_Queue;
}

But I can't guarantee that copy assignment and copy construction are equivalent functionality. 但我不能保证复制分配和复制构造是等效的功能。

Option 2: 选项2:

I could have a private method... 我可以有私人方法......

std::queue<T, Container> GetQueue() const
{
    std::lock_guard<std::mutex> lock(other.m_Mutex);
    return m_Queue;
}

And then in the constructor do this... 然后在构造函数中执行此操作...

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.GetQueue()) {}

But this potentially (depending on optimizations) uses m_Queue's copy constructor once and it's move constructor once. 但这可能(取决于优化)使用m_Queue的复制构造函数一次,它移动构造函数一次。 And I also can't guarantee that a copy and a move is equivalent to just a copy. 我也不能保证副本和移动只相当于副本。 Additionally the user provided container could be bizarre and be copyable but unmoveable, which would also cause this approach to have problems. 此外,用户提供的容器可能是奇怪的并且是可复制的但是不可移动的,这也会导致这种方法出现问题。

So, what do I do? 那么,我该怎么办?

ConcurrrentQueue::ConcurrrentQueue(
        ConcurrrentQueue const& other )
    : m_Queue( (std::lock_guard<std::mutex>( other.m_Mutex ),
               other.m_Queue ) )
{
}

should work. 应该管用。

Lock, create a copy of the content and then swap it with the member. 锁定,创建内容的副本,然后将其与成员交换。 At least that's the easiest and IMHO cleanest way. 至少那是最简单和恕我直言最干净的方式。 Another less clean way is to use the comma operator: (a, b) yields b , but if a is a scoped lock, the temporary will live until the next sequence point, ie until you have used b to initialize your local copy. 另一个不太干净的方法是使用逗号运算符: (a, b)产生b ,但如果a是一个范围锁,临时将一直存在直到下一个序列点,即直到你用b来初始化本地副本。

That said, there are two things to consider: 也就是说,有两件事需要考虑:

  • Maybe copying is not such a smart idea anyway and your design works as well if you just disable copying. 也许复制不是一个聪明的想法,如果你只是禁用复制,你的设计也可以。
  • If you have access to the queue and you can read it for copying, doesn't that imply that the mutex must already be locked? 如果您可以访问队列并且可以将其读取以进行复制,那是否意味着必须已锁定互斥锁? If not, how are you sure that you really want to copy the queue? 如果没有,您如何确定要真正复制队列? I don't question that there are answers that justify the design, but it's unusual. 我不怀疑有答案证明设计合理,但这是不寻常的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM